18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd - command line interface for hostapd daemon
3807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * Copyright (c) 2004-2015, 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"
139d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt#include "common/ieee802_11_defs.h"
141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/common.h"
151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/eloop.h"
161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/edit.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/version.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
201d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char *const hostapd_cli_version =
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"hostapd_cli v" VERSION_STR "\n"
22807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
251d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char *const hostapd_cli_license =
26c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt"This software may be distributed under the terms of the BSD license.\n"
27c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt"See README for more details.\n";
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
291d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char *const hostapd_cli_full_license =
30c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt"This software may be distributed under the terms of the BSD license.\n"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"Redistribution and use in source and binary forms, with or without\n"
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"modification, are permitted provided that the following conditions are\n"
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"met:\n"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"1. Redistributions of source code must retain the above copyright\n"
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   notice, this list of conditions and the following disclaimer.\n"
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"2. Redistributions in binary form must reproduce the above copyright\n"
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   notice, this list of conditions and the following disclaimer in the\n"
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   documentation and/or other materials provided with the distribution.\n"
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   names of its contributors may be used to endorse or promote products\n"
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   derived from this software without specific prior written permission.\n"
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n";
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
601d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char *const commands_help =
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"Commands:\n"
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   mib                  get MIB variables (dot1x, dot11, radius)\n"
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   sta <addr>           get MIB variables for one station\n"
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   all_sta              get MIB variables for all stations\n"
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   new_sta <addr>       add a new station\n"
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   deauthenticate <addr>  deauthenticate a station\n"
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   disassociate <addr>  disassociate a station\n"
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   sa_query <addr>      send SA Query to a station\n"
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_pin <uuid> <pin> [timeout] [addr]  add WPS Enrollee PIN\n"
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_check_pin <PIN>  verify PIN checksum\n"
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_pbc              indicate button pushed to initiate PBC\n"
7561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt"   wps_cancel           cancel the pending WPS operation\n"
7604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC
7704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt"   wps_nfc_tag_read <hexdump>  report read NFC tag with WPS data\n"
7804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt"   wps_nfc_config_token <WPS/NDEF>  build NFC configuration token\n"
7904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt"   wps_nfc_token <WPS/NDEF/enable/disable>  manager NFC password token\n"
8004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_ap_pin <cmd> [params..]  enable/disable AP PIN\n"
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_config <SSID> <auth> <encr> <key>  configure AP\n"
83b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt"   wps_get_status       show current WPS status\n"
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   get_config           show current configuration\n"
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   help                 show this usage help\n"
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   interface [ifname]   show interfaces/select interface\n"
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   level <debug level>  change debug level\n"
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   license              show full hostapd_cli license\n"
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   quit                 exit hostapd_cli\n";
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_ctrl *ctrl_conn;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_quit = 0;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_attached = 0;
95205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson
96205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson#ifndef CONFIG_CTRL_IFACE_DIR
97205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
98205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson#endif /* CONFIG_CTRL_IFACE_DIR */
99205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnsonstatic const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
100205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char *ctrl_ifname = NULL;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pid_file = NULL;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *action_file = NULL;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ping_interval = 5;
1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int interactive = 0;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void)
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr, "%s\n", hostapd_cli_version);
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr,
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"[-a<path>] \\\n"
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"                   [-G<ping interval>] [command..]\n"
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Options:\n"
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -h           help (show this usage text)\n"
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -v           shown version information\n"
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -p<path>     path to find control sockets (default: "
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"/var/run/hostapd)\n"
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -a<file>     run in daemon mode executing the action file "
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"based on events\n"
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"                from hostapd\n"
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -B           run a daemon in the background\n"
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -i<ifname>   Interface to listen on (default: first "
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"interface found in the\n"
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"                socket path)\n\n"
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"%s",
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		commands_help);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *cfile;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int flen;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ifname == NULL)
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cfile = malloc(flen);
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfile == NULL)
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctrl_conn = wpa_ctrl_open(cfile);
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	free(cfile);
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ctrl_conn;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_close_connection(void)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn == NULL)
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_cli_attached) {
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ctrl_detach(ctrl_conn);
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_attached = 0;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_ctrl_close(ctrl_conn);
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctrl_conn = NULL;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_msg_cb(char *msg, size_t len)
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("%s\n", msg);
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[4096];
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn == NULL) {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Not connected to hostapd - command dropped.\n");
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(buf) - 1;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       hostapd_cli_msg_cb);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret == -2) {
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("'%s' command timed out.\n", cmd);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ret < 0) {
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("'%s' command failed.\n", cmd);
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (print) {
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[len] = '\0';
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("%s", buf);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return _wpa_ctrl_command(ctrl, cmd, 1);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "PING");
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "RELOG");
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
220cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
221cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt{
222fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
223fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
224cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	return wpa_ctrl_command(ctrl, "STATUS");
225cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt}
226cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
227cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
230fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (argc > 0) {
231fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		char buf[100];
232fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
233fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return wpa_ctrl_command(ctrl, buf);
234fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "MIB");
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_exec(const char *program, const char *arg1,
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const char *arg2)
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
242772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	char *arg;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
246772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	len = os_strlen(arg1) + os_strlen(arg2) + 2;
247772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	arg = os_malloc(len);
248772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	if (arg == NULL)
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
250772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	os_snprintf(arg, len, "%s %s", arg1, arg2);
251772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	res = os_exec(program, arg, 1);
252772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	os_free(arg);
253772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
254772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	return res;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_action_process(char *msg, size_t len)
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pos;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = msg;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos == '<') {
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(pos, '>');
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos)
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos = msg;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_cli_exec(action_file, ctrl_ifname, pos);
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
278fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (argc < 1) {
279fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		printf("Invalid 'sta' command - at least one argument, STA "
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "address, is required.\n");
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
283fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (argc > 1)
284fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
285fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	else
286fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		snprintf(buf, sizeof(buf), "STA %s", argv[0]);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1) {
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'new_sta' command - exactly one argument, STA "
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "address, is required.\n");
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  char *argv[])
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'deauthenticate' command - exactly one "
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "argument, STA address, is required.\n");
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 1)
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    argv[0], argv[1]);
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					char *argv[])
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'disassociate' command - exactly one "
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "argument, STA address, is required.\n");
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 1)
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    argv[0], argv[1]);
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    char *argv[])
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1) {
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'sa_query' command - exactly one argument, "
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "STA address, is required.\n");
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 2) {
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'wps_pin' command - at least two arguments, "
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "UUID and PIN, are required.\n");
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 3)
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 argv[0], argv[1], argv[2], argv[3]);
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (argc > 2)
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 argv[0], argv[1], argv[2]);
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 char *argv[])
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char cmd[256];
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1 && argc != 2) {
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "- PIN to be verified\n");
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc == 2)
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  argv[0], argv[1]);
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  argv[0]);
3976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(cmd), res)) {
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Too long WPS_CHECK_PIN command.\n");
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "WPS_PBC");
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
41304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      char *argv[])
41404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
41504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
41604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
41704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
41804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
41904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC
42004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
42104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					    char *argv[])
42204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
42304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int ret;
42404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char *buf;
42504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	size_t buflen;
42604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
42704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (argc != 1) {
42804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Invalid 'wps_nfc_tag_read' command - one argument "
42904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       "is required.\n");
43004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
43104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
43204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
43304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	buflen = 18 + os_strlen(argv[0]);
43404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	buf = os_malloc(buflen);
43504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (buf == NULL)
43604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
43704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
43804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
43904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = wpa_ctrl_command(ctrl, buf);
44004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(buf);
44104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
44204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return ret;
44304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
44404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
44504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
44604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
44704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						int argc, char *argv[])
44804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
44904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char cmd[64];
45004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int res;
45104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
45204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (argc != 1) {
45304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Invalid 'wps_nfc_config_token' command - one argument "
45404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       "is required.\n");
45504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
45604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
45704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
45804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
45904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  argv[0]);
4606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(cmd), res)) {
46104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
46204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
46304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
46404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
46504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
46604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
46704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
46804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
46904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 int argc, char *argv[])
47004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
47104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char cmd[64];
47204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int res;
47304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
47404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (argc != 1) {
47504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Invalid 'wps_nfc_token' command - one argument is "
47604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       "required.\n");
47704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
47804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
47904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
48004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
4816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(cmd), res)) {
48204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Too long WPS_NFC_TOKEN command.\n");
48304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
48404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
48504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
48604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
487f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
488f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
489f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
490f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt						int argc, char *argv[])
491f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{
492f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	char cmd[64];
493f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	int res;
494f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
495f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (argc != 2) {
496f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		printf("Invalid 'nfc_get_handover_sel' command - two arguments "
497f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		       "are required.\n");
498f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return -1;
499f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
500f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
501f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
502f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			  argv[0], argv[1]);
5036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(cmd), res)) {
504f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		printf("Too long NFC_GET_HANDOVER_SEL command.\n");
505f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return -1;
506f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
507f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
508f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt}
509f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
51004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */
51104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
51204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      char *argv[])
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'wps_ap_pin' command - at least one argument "
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "is required.\n");
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 2)
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 argv[0], argv[1], argv[2]);
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (argc > 1)
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 argv[0], argv[1]);
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
534b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
535b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt					  char *argv[])
536b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{
537b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
538b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt}
539b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
540b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      char *argv[])
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
5459d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	char ssid_hex[2 * SSID_MAX_LEN + 1];
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char key_hex[2 * 64 + 1];
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'wps_config' command - at least two arguments "
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "are required.\n");
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid_hex[0] = '\0';
5569d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	for (i = 0; i < SSID_MAX_LEN; i++) {
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (argv[0][i] == '\0')
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_hex[0] = '\0';
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 3) {
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < 64; i++) {
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (argv[3][i] == '\0')
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_snprintf(&key_hex[i * 2], 3, "%02x",
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    argv[3][i]);
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 3)
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ssid_hex, argv[1], argv[2], key_hex);
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (argc > 2)
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ssid_hex, argv[1], argv[2]);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ssid_hex, argv[1]);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
586a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
587a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt					     char *argv[])
588a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
589a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	char buf[300];
590a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	int res;
591a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
592a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (argc < 2) {
593a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		printf("Invalid 'disassoc_imminent' command - two arguments "
594a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		       "(STA addr and Disassociation Timer) are needed\n");
595a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
596a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
597a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
598a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
599a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			  argv[0], argv[1]);
6006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(buf), res))
601a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
602a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
603a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
604a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
605a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
6061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
6071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					char *argv[])
6081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
6091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char buf[300];
6101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
612b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (argc < 3) {
613b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		printf("Invalid 'ess_disassoc' command - three arguments (STA "
614b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       "addr, disassoc timer, and URL) are needed\n");
6151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
6161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
618b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
619b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			  argv[0], argv[1], argv[2]);
6206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(buf), res))
6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
6276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				      char *argv[])
6286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
6296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	char buf[2000], *tmp;
6306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int res, i, total;
6316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (argc < 1) {
6336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
6346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
6356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
6366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
6386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(buf), res))
6396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
6406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	total = res;
6426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	for (i = 1; i < argc; i++) {
6436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		tmp = &buf[total];
6446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
6456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(sizeof(buf) - total, res))
6466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
6476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		total += res;
6486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
6496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
6506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
6516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      char *argv[])
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "GET_CONFIG");
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				char *addr, size_t addr_len)
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[4096], *pos;
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn == NULL) {
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Not connected to hostapd - command dropped.\n");
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(buf) - 1;
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       hostapd_cli_msg_cb);
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret == -2) {
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("'%s' command timed out.\n", cmd);
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ret < 0) {
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("'%s' command failed.\n", cmd);
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[len] = '\0';
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (memcmp(buf, "FAIL", 4) == 0)
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("%s", buf);
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*pos != '\0' && *pos != '\n')
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = '\0';
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr, buf, addr_len);
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char addr[32], cmd[64];
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("%s", commands_help);
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
726051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
727051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					   int argc, char *argv[])
728051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
729051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char buf[200];
730051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int res;
731051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
732051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (argc != 1) {
733051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		printf("Invalid 'set_qos_map_set' command - "
734051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		       "one argument (comma delimited QoS map set) "
735051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		       "is needed\n");
736051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return -1;
737051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
738051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
739051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
7406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(buf), res))
741051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return -1;
742051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
743051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
744051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
745051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
746051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
747051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					     int argc, char *argv[])
748051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
749051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char buf[50];
750051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int res;
751051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
752051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (argc != 1) {
753051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		printf("Invalid 'send_qos_map_conf' command - "
754051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		       "one argument (STA addr) is needed\n");
755051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return -1;
756051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
757051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
758051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
7596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(buf), res))
760051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return -1;
761051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
762051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
763051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
764051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
765f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
766f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt					  char *argv[])
767f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{
768f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	char buf[300];
769f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	int res;
770f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
771f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (argc < 2) {
772f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
773f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       "addr and URL) are needed\n");
774f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return -1;
775f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	}
776f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
777f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
778f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			  argv[0], argv[1]);
7796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(buf), res))
780f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return -1;
781f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
782f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt}
783f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
784f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
785f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
786f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt					   char *argv[])
787f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{
788f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	char buf[300];
789f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	int res;
790f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
791f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (argc < 3) {
792f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
793f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return -1;
794f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	}
795f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
796f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (argc > 3)
797f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		res = os_snprintf(buf, sizeof(buf),
798f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				  "HS20_DEAUTH_REQ %s %s %s %s",
799f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				  argv[0], argv[1], argv[2], argv[3]);
800f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	else
801f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		res = os_snprintf(buf, sizeof(buf),
802f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				  "HS20_DEAUTH_REQ %s %s %s",
803f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				  argv[0], argv[1], argv[2]);
8046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(buf), res))
805f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return -1;
806f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
807f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt}
808f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
809f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_cli_quit = 1;
8131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (interactive)
8141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_terminate();
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char cmd[256];
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1) {
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid LEVEL command: needs one argument (debug "
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "level)\n");
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dirent *dent;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DIR *dir;
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dir = opendir(ctrl_iface_dir);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dir == NULL) {
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Control interface directory '%s' could not be "
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "openned.\n", ctrl_iface_dir);
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Available interfaces:\n");
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((dent = readdir(dir))) {
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strcmp(dent->d_name, ".") == 0 ||
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    strcmp(dent->d_name, "..") == 0)
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("%s\n", dent->d_name);
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	closedir(dir);
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     char *argv[])
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_list_interfaces(ctrl);
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_cli_close_connection();
864717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	os_free(ctrl_ifname);
865717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	ctrl_ifname = os_strdup(argv[0]);
866661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (ctrl_ifname == NULL)
867661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return -1;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_cli_open_connection(ctrl_ifname)) {
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Connected to interface '%s.\n", ctrl_ifname);
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_ctrl_attach(ctrl_conn) == 0) {
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_cli_attached = 1;
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Warning: Failed to attach to "
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "hostapd.\n");
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not connect to interface '%s' - re-trying\n",
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ctrl_ifname);
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char cmd[256];
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 2) {
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid SET command: needs two arguments (variable "
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "name and value)\n");
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
8976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(cmd), res)) {
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Too long SET command.\n");
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char cmd[256];
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1) {
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid GET command: needs one argument (variable "
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "name)\n");
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
9176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(cmd), res)) {
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Too long GET command.\n");
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
925e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtstatic int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
926e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				       int argc, char *argv[])
927e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{
928e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	char cmd[256];
929e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	int res;
930e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	int i;
931e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	char *tmp;
932e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	int total;
933e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
934e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	if (argc < 2) {
935e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		printf("Invalid chan_switch command: needs at least two "
936e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		       "arguments (count and freq)\n"
937e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		       "usage: <cs_count> <freq> [sec_channel_offset=] "
938e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		       "[center_freq1=] [center_freq2=] [bandwidth=] "
939e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		       "[blocktx] [ht|vht]\n");
940e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		return -1;
941e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	}
942e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
943e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
944e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			  argv[0], argv[1]);
9456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(cmd), res)) {
946e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		printf("Too long CHAN_SWITCH command.\n");
947e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		return -1;
948e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	}
949e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
950e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	total = res;
951e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	for (i = 2; i < argc; i++) {
952e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		tmp = cmd + total;
953e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
9546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(sizeof(cmd) - total, res)) {
955e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			printf("Too long CHAN_SWITCH command.\n");
956e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			return -1;
957e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		}
958e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		total += res;
959e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	}
960e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
961e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt}
962e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
963e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
9646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
9656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				      char *argv[])
9666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
9676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return wpa_ctrl_command(ctrl, "ENABLE");
9686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
9696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
9726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				      char *argv[])
9736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
9746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return wpa_ctrl_command(ctrl, "RELOAD");
9756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
9766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
9796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				      char *argv[])
9806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
9816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return wpa_ctrl_command(ctrl, "DISABLE");
9826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
9836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
985df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtstatic int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
986df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{
987df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	char cmd[256];
988df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	int res;
989df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
990df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	if (argc < 2 || argc > 3) {
991df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		printf("Invalid vendor command\n"
992df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		       "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
993df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		return -1;
994df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	}
995df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
996df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
997df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt			  argc == 3 ? argv[2] : "");
9986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(sizeof(cmd), res)) {
999df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		printf("Too long VENDOR command.\n");
1000df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		return -1;
1001df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	}
1002df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
1003df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt}
1004df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
1005df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
10066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
10076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				     char *argv[])
10086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
10096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return wpa_ctrl_command(ctrl, "ERP_FLUSH");
10106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
10116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct hostapd_cli_cmd {
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *cmd;
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10181d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const struct hostapd_cli_cmd hostapd_cli_commands[] = {
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "ping", hostapd_cli_cmd_ping },
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "mib", hostapd_cli_cmd_mib },
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "relog", hostapd_cli_cmd_relog },
1022cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	{ "status", hostapd_cli_cmd_status },
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "sta", hostapd_cli_cmd_sta },
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "all_sta", hostapd_cli_cmd_all_sta },
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "new_sta", hostapd_cli_cmd_new_sta },
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "deauthenticate", hostapd_cli_cmd_deauthenticate },
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "disassociate", hostapd_cli_cmd_disassociate },
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "sa_query", hostapd_cli_cmd_sa_query },
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_pin", hostapd_cli_cmd_wps_pin },
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_pbc", hostapd_cli_cmd_wps_pbc },
103504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	{ "wps_cancel", hostapd_cli_cmd_wps_cancel },
103604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC
103704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
103804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
103904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
1040f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	{ "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
104104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_config", hostapd_cli_cmd_wps_config },
1044b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	{ "wps_get_status", hostapd_cli_cmd_wps_get_status },
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
1046a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
10471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
10486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	{ "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "get_config", hostapd_cli_cmd_get_config },
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "help", hostapd_cli_cmd_help },
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "interface", hostapd_cli_cmd_interface },
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "level", hostapd_cli_cmd_level },
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "license", hostapd_cli_cmd_license },
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "quit", hostapd_cli_cmd_quit },
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "set", hostapd_cli_cmd_set },
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "get", hostapd_cli_cmd_get },
1057051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	{ "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
1058051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
1059e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	{ "chan_switch", hostapd_cli_cmd_chan_switch },
1060f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
1061f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
1062df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	{ "vendor", hostapd_cli_cmd_vendor },
10636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	{ "enable", hostapd_cli_cmd_enable },
10646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	{ "reload", hostapd_cli_cmd_reload },
10656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	{ "disable", hostapd_cli_cmd_disable },
10666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	{ "erp_flush", hostapd_cli_cmd_erp_flush },
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ NULL, NULL }
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10731d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt	const struct hostapd_cli_cmd *cmd, *match = NULL;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int count;
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = 0;
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd = hostapd_cli_commands;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cmd->cmd) {
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			match = cmd;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* we have an exact match */
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				count = 1;
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			count++;
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmd++;
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count > 1) {
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Ambiguous command '%s'; possible commands:", argv[0]);
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmd = hostapd_cli_commands;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (cmd->cmd) {
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    0) {
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf(" %s", cmd->cmd);
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cmd++;
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\n");
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (count == 0) {
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Unknown command '%s'\n", argv[0]);
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		match->handler(ctrl, argc - 1, &argv[1]);
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int action_monitor)
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int first = 1;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn == NULL)
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (wpa_ctrl_pending(ctrl)) {
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char buf[256];
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t len = sizeof(buf) - 1;
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf[len] = '\0';
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (action_monitor)
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hostapd_cli_action_process(buf, len);
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else {
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (in_read && first)
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					printf("\n");
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				first = 0;
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("%s\n", buf);
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Could not read pending message.\n");
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define max_args 10
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int tokenize_cmd(char *cmd, char *argv[])
11401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos;
11421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int argc = 0;
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = cmd;
11451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (;;) {
11461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		while (*pos == ' ')
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
11481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (*pos == '\0')
11491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
11501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		argv[argc] = pos;
11511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		argc++;
11521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (argc == max_args)
11531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
11541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (*pos == '"') {
11551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			char *pos2 = os_strrchr(pos, '"');
11561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (pos2)
11571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				pos = pos2 + 1;
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		while (*pos != '\0' && *pos != ' ')
11601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			pos++;
11611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (*pos == ' ')
11621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			*pos++ = '\0';
11631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return argc;
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Connection to hostapd lost - trying to reconnect\n");
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_close_connection();
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ctrl_conn) {
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ctrl_conn) {
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Connection to hostapd re-established\n");
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_ctrl_attach(ctrl_conn) == 0) {
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hostapd_cli_attached = 1;
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("Warning: Failed to attach to "
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "hostapd.\n");
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn)
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_recv_pending(ctrl_conn, 1, 0);
11891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
11901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
11941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_terminate();
11961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
12001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
12011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *argv[max_args];
12021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int argc;
12031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	argc = tokenize_cmd(cmd, argv);
12041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (argc)
12051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_request(ctrl_conn, argc, argv);
12061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
12071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_edit_eof_cb(void *ctx)
12101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
12111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_terminate();
12121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
12131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_interactive(void)
12161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
12171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	printf("\nInteractive mode\n\n");
12181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
12201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
122161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		  NULL, NULL, NULL, NULL);
12221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
12231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_run();
12251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	edit_deinit(NULL, NULL);
12271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
12281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
12291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_cleanup(void)
12321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
12331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	hostapd_cli_close_connection();
12341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (pid_file)
12351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_daemonize_terminate(pid_file);
12361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_program_deinit();
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_action(struct wpa_ctrl *ctrl)
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd_set rfds;
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int fd, res;
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct timeval tv;
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd = wpa_ctrl_get_fd(ctrl);
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (!hostapd_cli_quit) {
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FD_ZERO(&rfds);
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FD_SET(fd, &rfds);
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tv.tv_sec = ping_interval;
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tv.tv_usec = 0;
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = select(fd + 1, &rfds, NULL, NULL, &tv);
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 && errno != EINTR) {
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			perror("select");
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (FD_ISSET(fd, &rfds))
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_cli_recv_pending(ctrl, 0, 1);
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(buf) - 1;
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     hostapd_cli_action_process) < 0 ||
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("hostapd did not reply to PING "
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "command - exiting\n");
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[])
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int warning_displayed = 0;
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c;
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int daemonize = 0;
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_program_init())
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		c = getopt(argc, argv, "a:BhG:i:p:v");
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c < 0)
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (c) {
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'a':
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			action_file = optarg;
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'B':
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			daemonize = 1;
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'G':
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ping_interval = atoi(optarg);
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'h':
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'v':
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s\n", hostapd_cli_version);
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'i':
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctrl_ifname);
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ctrl_ifname = os_strdup(optarg);
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'p':
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ctrl_iface_dir = optarg;
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	interactive = (argc == optind) && (action_file == NULL);
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interactive) {
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("%s\n\n%s\n\n", hostapd_cli_version,
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       hostapd_cli_license);
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (eloop_init())
13281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
13291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ctrl_ifname == NULL) {
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			struct dirent *dent;
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			DIR *dir = opendir(ctrl_iface_dir);
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dir) {
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				while ((dent = readdir(dir))) {
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					if (os_strcmp(dent->d_name, ".") == 0
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    ||
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    os_strcmp(dent->d_name, "..") == 0)
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						continue;
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					printf("Selected interface '%s'\n",
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dent->d_name);
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					ctrl_ifname = os_strdup(dent->d_name);
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					break;
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				closedir(dir);
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ctrl_conn) {
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (warning_displayed)
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("Connection established.\n");
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!interactive) {
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			perror("Failed to connect to hostapd - "
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "wpa_ctrl_open");
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!warning_displayed) {
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Could not connect to hostapd - re-trying\n");
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			warning_displayed = 1;
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_sleep(1, 0);
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		continue;
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interactive || action_file) {
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_ctrl_attach(ctrl_conn) == 0) {
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_cli_attached = 1;
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Warning: Failed to attach to hostapd.\n");
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (action_file)
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (daemonize && os_daemonize(pid_file))
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interactive)
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_interactive();
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (action_file)
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_action(ctrl_conn);
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctrl_ifname);
13901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_destroy();
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_cli_cleanup();
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1394