2 * hostapd - command line interface for hostapd daemon
3 * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "common/wpa_ctrl.h"
13 #include "common/ieee802_11_defs.h"
14 #include "utils/common.h"
15 #include "utils/eloop.h"
16 #include "utils/edit.h"
17 #include "common/version.h"
19 #ifndef CONFIG_NO_CTRL_IFACE
21 static const char *const hostapd_cli_version =
22 "hostapd_cli v" VERSION_STR "\n"
23 "Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
26 static const char *const hostapd_cli_license =
27 "This software may be distributed under the terms of the BSD license.\n"
28 "See README for more details.\n";
30 static const char *const hostapd_cli_full_license =
31 "This software may be distributed under the terms of the BSD license.\n"
33 "Redistribution and use in source and binary forms, with or without\n"
34 "modification, are permitted provided that the following conditions are\n"
37 "1. Redistributions of source code must retain the above copyright\n"
38 " notice, this list of conditions and the following disclaimer.\n"
40 "2. Redistributions in binary form must reproduce the above copyright\n"
41 " notice, this list of conditions and the following disclaimer in the\n"
42 " documentation and/or other materials provided with the distribution.\n"
44 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
45 " names of its contributors may be used to endorse or promote products\n"
46 " derived from this software without specific prior written permission.\n"
48 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
49 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
50 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
51 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
52 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
53 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
54 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
55 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
56 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
57 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
58 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
61 static const char *const commands_help =
63 " mib get MIB variables (dot1x, dot11, radius)\n"
64 " sta <addr> get MIB variables for one station\n"
65 " all_sta get MIB variables for all stations\n"
66 " new_sta <addr> add a new station\n"
67 " deauthenticate <addr> deauthenticate a station\n"
68 " disassociate <addr> disassociate a station\n"
69 #ifdef CONFIG_IEEE80211W
70 " sa_query <addr> send SA Query to a station\n"
71 #endif /* CONFIG_IEEE80211W */
73 " wps_pin <uuid> <pin> [timeout] [addr] add WPS Enrollee PIN\n"
74 " wps_check_pin <PIN> verify PIN checksum\n"
75 " wps_pbc indicate button pushed to initiate PBC\n"
76 " wps_cancel cancel the pending WPS operation\n"
78 " wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
79 " wps_nfc_config_token <WPS/NDEF> build NFC configuration token\n"
80 " wps_nfc_token <WPS/NDEF/enable/disable> manager NFC password token\n"
81 #endif /* CONFIG_WPS_NFC */
82 " wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
83 " wps_config <SSID> <auth> <encr> <key> configure AP\n"
84 " wps_get_status show current WPS status\n"
85 #endif /* CONFIG_WPS */
86 " get_config show current configuration\n"
87 " help show this usage help\n"
88 " interface [ifname] show interfaces/select interface\n"
89 " level <debug level> change debug level\n"
90 " license show full hostapd_cli license\n"
91 " quit exit hostapd_cli\n";
93 static struct wpa_ctrl *ctrl_conn;
94 static int hostapd_cli_quit = 0;
95 static int hostapd_cli_attached = 0;
97 #ifndef CONFIG_CTRL_IFACE_DIR
98 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
99 #endif /* CONFIG_CTRL_IFACE_DIR */
100 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
101 static const char *client_socket_dir = NULL;
103 static char *ctrl_ifname = NULL;
104 static const char *pid_file = NULL;
105 static const char *action_file = NULL;
106 static int ping_interval = 5;
107 static int interactive = 0;
110 static void usage(void)
112 fprintf(stderr, "%s\n", hostapd_cli_version);
115 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
117 " [-P<pid file>] [-G<ping interval>] [command..]\n"
120 " -h help (show this usage text)\n"
121 " -v shown version information\n"
122 " -p<path> path to find control sockets (default: "
123 "/var/run/hostapd)\n"
124 " -s<dir_path> dir path to open client sockets (default: "
125 CONFIG_CTRL_IFACE_DIR ")\n"
126 " -a<file> run in daemon mode executing the action file "
129 " -B run a daemon in the background\n"
130 " -i<ifname> Interface to listen on (default: first "
131 "interface found in the\n"
138 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
140 #ifndef CONFIG_CTRL_IFACE_UDP
143 #endif /* !CONFIG_CTRL_IFACE_UDP */
148 #ifdef CONFIG_CTRL_IFACE_UDP
149 ctrl_conn = wpa_ctrl_open(ifname);
151 #else /* CONFIG_CTRL_IFACE_UDP */
152 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
153 cfile = malloc(flen);
156 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
158 if (client_socket_dir && client_socket_dir[0] &&
159 access(client_socket_dir, F_OK) < 0) {
160 perror(client_socket_dir);
165 ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
168 #endif /* CONFIG_CTRL_IFACE_UDP */
172 static void hostapd_cli_close_connection(void)
174 if (ctrl_conn == NULL)
177 if (hostapd_cli_attached) {
178 wpa_ctrl_detach(ctrl_conn);
179 hostapd_cli_attached = 0;
181 wpa_ctrl_close(ctrl_conn);
186 static void hostapd_cli_msg_cb(char *msg, size_t len)
192 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
198 if (ctrl_conn == NULL) {
199 printf("Not connected to hostapd - command dropped.\n");
202 len = sizeof(buf) - 1;
203 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
206 printf("'%s' command timed out.\n", cmd);
208 } else if (ret < 0) {
209 printf("'%s' command failed.\n", cmd);
220 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
222 return _wpa_ctrl_command(ctrl, cmd, 1);
226 static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
235 res = os_snprintf(pos, end - pos, "%s", cmd);
236 if (os_snprintf_error(end - pos, res))
240 for (i = 0; i < argc; i++) {
241 res = os_snprintf(pos, end - pos, " %s", argv[i]);
242 if (os_snprintf_error(end - pos, res))
247 buf[buflen - 1] = '\0';
251 printf("Too long command\n");
256 static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
257 int min_args, int argc, char *argv[])
261 if (argc < min_args) {
262 printf("Invalid %s command - at least %d argument%s required.\n",
263 cmd, min_args, min_args > 1 ? "s are" : " is");
266 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
268 return wpa_ctrl_command(ctrl, buf);
272 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
274 return wpa_ctrl_command(ctrl, "PING");
278 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
280 return wpa_ctrl_command(ctrl, "RELOG");
284 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
286 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
287 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
288 return wpa_ctrl_command(ctrl, "STATUS");
292 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
296 os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
297 return wpa_ctrl_command(ctrl, buf);
299 return wpa_ctrl_command(ctrl, "MIB");
303 static int hostapd_cli_exec(const char *program, const char *arg1,
310 len = os_strlen(arg1) + os_strlen(arg2) + 2;
311 arg = os_malloc(len);
314 os_snprintf(arg, len, "%s %s", arg1, arg2);
315 res = os_exec(program, arg, 1);
322 static void hostapd_cli_action_process(char *msg, size_t len)
328 pos = os_strchr(pos, '>');
335 hostapd_cli_exec(action_file, ctrl_ifname, pos);
339 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
343 printf("Invalid 'sta' command - at least one argument, STA "
344 "address, is required.\n");
348 snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
350 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
351 return wpa_ctrl_command(ctrl, buf);
355 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
360 printf("Invalid 'new_sta' command - exactly one argument, STA "
361 "address, is required.\n");
364 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
365 return wpa_ctrl_command(ctrl, buf);
369 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
374 printf("Invalid 'deauthenticate' command - exactly one "
375 "argument, STA address, is required.\n");
379 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
382 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
383 return wpa_ctrl_command(ctrl, buf);
387 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
392 printf("Invalid 'disassociate' command - exactly one "
393 "argument, STA address, is required.\n");
397 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
400 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
401 return wpa_ctrl_command(ctrl, buf);
405 #ifdef CONFIG_IEEE80211W
406 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
411 printf("Invalid 'sa_query' command - exactly one argument, "
412 "STA address, is required.\n");
415 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
416 return wpa_ctrl_command(ctrl, buf);
418 #endif /* CONFIG_IEEE80211W */
422 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
427 printf("Invalid 'wps_pin' command - at least two arguments, "
428 "UUID and PIN, are required.\n");
432 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
433 argv[0], argv[1], argv[2], argv[3]);
435 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
436 argv[0], argv[1], argv[2]);
438 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
439 return wpa_ctrl_command(ctrl, buf);
443 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
449 if (argc != 1 && argc != 2) {
450 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
451 "- PIN to be verified\n");
456 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
459 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
461 if (os_snprintf_error(sizeof(cmd), res)) {
462 printf("Too long WPS_CHECK_PIN command.\n");
465 return wpa_ctrl_command(ctrl, cmd);
469 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
472 return wpa_ctrl_command(ctrl, "WPS_PBC");
476 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
479 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
483 #ifdef CONFIG_WPS_NFC
484 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
492 printf("Invalid 'wps_nfc_tag_read' command - one argument "
497 buflen = 18 + os_strlen(argv[0]);
498 buf = os_malloc(buflen);
501 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
503 ret = wpa_ctrl_command(ctrl, buf);
510 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
511 int argc, char *argv[])
517 printf("Invalid 'wps_nfc_config_token' command - one argument "
522 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
524 if (os_snprintf_error(sizeof(cmd), res)) {
525 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
528 return wpa_ctrl_command(ctrl, cmd);
532 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
533 int argc, char *argv[])
539 printf("Invalid 'wps_nfc_token' command - one argument is "
544 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
545 if (os_snprintf_error(sizeof(cmd), res)) {
546 printf("Too long WPS_NFC_TOKEN command.\n");
549 return wpa_ctrl_command(ctrl, cmd);
553 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
554 int argc, char *argv[])
560 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
565 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
567 if (os_snprintf_error(sizeof(cmd), res)) {
568 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
571 return wpa_ctrl_command(ctrl, cmd);
574 #endif /* CONFIG_WPS_NFC */
577 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
582 printf("Invalid 'wps_ap_pin' command - at least one argument "
587 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
588 argv[0], argv[1], argv[2]);
590 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
593 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
594 return wpa_ctrl_command(ctrl, buf);
598 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
601 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
605 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
609 char ssid_hex[2 * SSID_MAX_LEN + 1];
610 char key_hex[2 * 64 + 1];
614 printf("Invalid 'wps_config' command - at least two arguments "
620 for (i = 0; i < SSID_MAX_LEN; i++) {
621 if (argv[0][i] == '\0')
623 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
628 for (i = 0; i < 64; i++) {
629 if (argv[3][i] == '\0')
631 os_snprintf(&key_hex[i * 2], 3, "%02x",
637 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
638 ssid_hex, argv[1], argv[2], key_hex);
640 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
641 ssid_hex, argv[1], argv[2]);
643 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
645 return wpa_ctrl_command(ctrl, buf);
647 #endif /* CONFIG_WPS */
650 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
657 printf("Invalid 'disassoc_imminent' command - two arguments "
658 "(STA addr and Disassociation Timer) are needed\n");
662 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
664 if (os_snprintf_error(sizeof(buf), res))
666 return wpa_ctrl_command(ctrl, buf);
670 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
677 printf("Invalid 'ess_disassoc' command - three arguments (STA "
678 "addr, disassoc timer, and URL) are needed\n");
682 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
683 argv[0], argv[1], argv[2]);
684 if (os_snprintf_error(sizeof(buf), res))
686 return wpa_ctrl_command(ctrl, buf);
690 static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
693 char buf[2000], *tmp;
697 printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
701 res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
702 if (os_snprintf_error(sizeof(buf), res))
706 for (i = 1; i < argc; i++) {
708 res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
709 if (os_snprintf_error(sizeof(buf) - total, res))
713 return wpa_ctrl_command(ctrl, buf);
717 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
720 return wpa_ctrl_command(ctrl, "GET_CONFIG");
724 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
725 char *addr, size_t addr_len)
727 char buf[4096], *pos;
731 if (ctrl_conn == NULL) {
732 printf("Not connected to hostapd - command dropped.\n");
735 len = sizeof(buf) - 1;
736 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
739 printf("'%s' command timed out.\n", cmd);
741 } else if (ret < 0) {
742 printf("'%s' command failed.\n", cmd);
747 if (memcmp(buf, "FAIL", 4) == 0)
752 while (*pos != '\0' && *pos != '\n')
755 os_strlcpy(addr, buf, addr_len);
760 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
763 char addr[32], cmd[64];
765 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
768 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
769 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
775 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
777 printf("%s", commands_help);
782 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
785 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
790 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
791 int argc, char *argv[])
797 printf("Invalid 'set_qos_map_set' command - "
798 "one argument (comma delimited QoS map set) "
803 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
804 if (os_snprintf_error(sizeof(buf), res))
806 return wpa_ctrl_command(ctrl, buf);
810 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
811 int argc, char *argv[])
817 printf("Invalid 'send_qos_map_conf' command - "
818 "one argument (STA addr) is needed\n");
822 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
823 if (os_snprintf_error(sizeof(buf), res))
825 return wpa_ctrl_command(ctrl, buf);
829 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
836 printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
837 "addr and URL) are needed\n");
841 res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
843 if (os_snprintf_error(sizeof(buf), res))
845 return wpa_ctrl_command(ctrl, buf);
849 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
856 printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
861 res = os_snprintf(buf, sizeof(buf),
862 "HS20_DEAUTH_REQ %s %s %s %s",
863 argv[0], argv[1], argv[2], argv[3]);
865 res = os_snprintf(buf, sizeof(buf),
866 "HS20_DEAUTH_REQ %s %s %s",
867 argv[0], argv[1], argv[2]);
868 if (os_snprintf_error(sizeof(buf), res))
870 return wpa_ctrl_command(ctrl, buf);
874 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
876 hostapd_cli_quit = 1;
883 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
887 printf("Invalid LEVEL command: needs one argument (debug "
891 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
892 return wpa_ctrl_command(ctrl, cmd);
896 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
901 dir = opendir(ctrl_iface_dir);
903 printf("Control interface directory '%s' could not be "
904 "openned.\n", ctrl_iface_dir);
908 printf("Available interfaces:\n");
909 while ((dent = readdir(dir))) {
910 if (strcmp(dent->d_name, ".") == 0 ||
911 strcmp(dent->d_name, "..") == 0)
913 printf("%s\n", dent->d_name);
919 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
923 hostapd_cli_list_interfaces(ctrl);
927 hostapd_cli_close_connection();
928 os_free(ctrl_ifname);
929 ctrl_ifname = os_strdup(argv[0]);
930 if (ctrl_ifname == NULL)
933 if (hostapd_cli_open_connection(ctrl_ifname)) {
934 printf("Connected to interface '%s.\n", ctrl_ifname);
935 if (wpa_ctrl_attach(ctrl_conn) == 0) {
936 hostapd_cli_attached = 1;
938 printf("Warning: Failed to attach to "
942 printf("Could not connect to interface '%s' - re-trying\n",
949 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
955 printf("Invalid SET command: needs two arguments (variable "
956 "name and value)\n");
960 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
961 if (os_snprintf_error(sizeof(cmd), res)) {
962 printf("Too long SET command.\n");
965 return wpa_ctrl_command(ctrl, cmd);
969 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
975 printf("Invalid GET command: needs one argument (variable "
980 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
981 if (os_snprintf_error(sizeof(cmd), res)) {
982 printf("Too long GET command.\n");
985 return wpa_ctrl_command(ctrl, cmd);
990 static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
998 printf("FST command: parameters are required.\n");
1002 total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
1004 for (i = 0; i < argc; i++) {
1005 res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
1007 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1008 printf("Too long fst command.\n");
1013 return wpa_ctrl_command(ctrl, cmd);
1015 #endif /* CONFIG_FST */
1018 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
1019 int argc, char *argv[])
1028 printf("Invalid chan_switch command: needs at least two "
1029 "arguments (count and freq)\n"
1030 "usage: <cs_count> <freq> [sec_channel_offset=] "
1031 "[center_freq1=] [center_freq2=] [bandwidth=] "
1032 "[blocktx] [ht|vht]\n");
1036 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
1038 if (os_snprintf_error(sizeof(cmd), res)) {
1039 printf("Too long CHAN_SWITCH command.\n");
1044 for (i = 2; i < argc; i++) {
1046 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
1047 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1048 printf("Too long CHAN_SWITCH command.\n");
1053 return wpa_ctrl_command(ctrl, cmd);
1057 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
1060 return wpa_ctrl_command(ctrl, "ENABLE");
1064 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
1067 return wpa_ctrl_command(ctrl, "RELOAD");
1071 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
1074 return wpa_ctrl_command(ctrl, "DISABLE");
1078 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
1083 if (argc < 2 || argc > 3) {
1084 printf("Invalid vendor command\n"
1085 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
1089 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
1090 argc == 3 ? argv[2] : "");
1091 if (os_snprintf_error(sizeof(cmd), res)) {
1092 printf("Too long VENDOR command.\n");
1095 return wpa_ctrl_command(ctrl, cmd);
1099 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1102 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1106 static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
1112 res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
1113 argc >= 1 ? " " : "",
1114 argc >= 1 ? argv[0] : "",
1115 argc == 2 ? " " : "",
1116 argc == 2 ? argv[1] : "");
1117 if (os_snprintf_error(sizeof(cmd), res)) {
1118 printf("Too long option\n");
1121 return wpa_ctrl_command(ctrl, cmd);
1125 static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
1129 return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
1133 static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1135 return wpa_ctrl_command(ctrl, "PMKSA");
1139 static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
1142 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
1146 static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
1152 if (argc < 3 || argc > 5) {
1153 printf("Invalid set_neighbor command: needs 3-5 arguments\n");
1157 res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
1158 argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
1159 argc == 5 ? argv[4] : "");
1160 if (os_snprintf_error(sizeof(cmd), res)) {
1161 printf("Too long SET_NEIGHBOR command.\n");
1164 return wpa_ctrl_command(ctrl, cmd);
1168 static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
1175 printf("Invalid remove_neighbor command: needs 2 arguments\n");
1179 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
1181 if (os_snprintf_error(sizeof(cmd), res)) {
1182 printf("Too long REMOVE_NEIGHBOR command.\n");
1185 return wpa_ctrl_command(ctrl, cmd);
1189 static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
1196 printf("Invalid req_lci command - requires destination address\n");
1200 res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
1201 if (os_snprintf_error(sizeof(cmd), res)) {
1202 printf("Too long REQ_LCI command.\n");
1205 return wpa_ctrl_command(ctrl, cmd);
1209 static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
1213 printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
1217 return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
1221 struct hostapd_cli_cmd {
1223 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1226 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1227 { "ping", hostapd_cli_cmd_ping },
1228 { "mib", hostapd_cli_cmd_mib },
1229 { "relog", hostapd_cli_cmd_relog },
1230 { "status", hostapd_cli_cmd_status },
1231 { "sta", hostapd_cli_cmd_sta },
1232 { "all_sta", hostapd_cli_cmd_all_sta },
1233 { "new_sta", hostapd_cli_cmd_new_sta },
1234 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
1235 { "disassociate", hostapd_cli_cmd_disassociate },
1236 #ifdef CONFIG_IEEE80211W
1237 { "sa_query", hostapd_cli_cmd_sa_query },
1238 #endif /* CONFIG_IEEE80211W */
1240 { "wps_pin", hostapd_cli_cmd_wps_pin },
1241 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
1242 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
1243 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
1244 #ifdef CONFIG_WPS_NFC
1245 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
1246 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
1247 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
1248 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
1249 #endif /* CONFIG_WPS_NFC */
1250 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
1251 { "wps_config", hostapd_cli_cmd_wps_config },
1252 { "wps_get_status", hostapd_cli_cmd_wps_get_status },
1253 #endif /* CONFIG_WPS */
1254 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
1255 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
1256 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
1257 { "get_config", hostapd_cli_cmd_get_config },
1258 { "help", hostapd_cli_cmd_help },
1259 { "interface", hostapd_cli_cmd_interface },
1261 { "fst", hostapd_cli_cmd_fst },
1262 #endif /* CONFIG_FST */
1263 { "raw", hostapd_cli_cmd_raw },
1264 { "level", hostapd_cli_cmd_level },
1265 { "license", hostapd_cli_cmd_license },
1266 { "quit", hostapd_cli_cmd_quit },
1267 { "set", hostapd_cli_cmd_set },
1268 { "get", hostapd_cli_cmd_get },
1269 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
1270 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
1271 { "chan_switch", hostapd_cli_cmd_chan_switch },
1272 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
1273 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
1274 { "vendor", hostapd_cli_cmd_vendor },
1275 { "enable", hostapd_cli_cmd_enable },
1276 { "reload", hostapd_cli_cmd_reload },
1277 { "disable", hostapd_cli_cmd_disable },
1278 { "erp_flush", hostapd_cli_cmd_erp_flush },
1279 { "log_level", hostapd_cli_cmd_log_level },
1280 { "pmksa", hostapd_cli_cmd_pmksa },
1281 { "pmksa_flush", hostapd_cli_cmd_pmksa_flush },
1282 { "set_neighbor", hostapd_cli_cmd_set_neighbor },
1283 { "remove_neighbor", hostapd_cli_cmd_remove_neighbor },
1284 { "req_lci", hostapd_cli_cmd_req_lci },
1285 { "req_range", hostapd_cli_cmd_req_range },
1290 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1292 const struct hostapd_cli_cmd *cmd, *match = NULL;
1296 cmd = hostapd_cli_commands;
1298 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1300 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1301 /* we have an exact match */
1311 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1312 cmd = hostapd_cli_commands;
1314 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1316 printf(" %s", cmd->cmd);
1321 } else if (count == 0) {
1322 printf("Unknown command '%s'\n", argv[0]);
1324 match->handler(ctrl, argc - 1, &argv[1]);
1329 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1333 if (ctrl_conn == NULL)
1335 while (wpa_ctrl_pending(ctrl)) {
1337 size_t len = sizeof(buf) - 1;
1338 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1341 hostapd_cli_action_process(buf, len);
1343 if (in_read && first)
1346 printf("%s\n", buf);
1349 printf("Could not read pending message.\n");
1358 static int tokenize_cmd(char *cmd, char *argv[])
1371 if (argc == max_args)
1374 char *pos2 = os_strrchr(pos, '"');
1378 while (*pos != '\0' && *pos != ' ')
1388 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1390 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1391 printf("Connection to hostapd lost - trying to reconnect\n");
1392 hostapd_cli_close_connection();
1395 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1397 printf("Connection to hostapd re-established\n");
1398 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1399 hostapd_cli_attached = 1;
1401 printf("Warning: Failed to attach to "
1407 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1408 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1412 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1418 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1420 char *argv[max_args];
1422 argc = tokenize_cmd(cmd, argv);
1424 wpa_request(ctrl_conn, argc, argv);
1428 static void hostapd_cli_edit_eof_cb(void *ctx)
1434 static void hostapd_cli_interactive(void)
1436 printf("\nInteractive mode\n\n");
1438 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1439 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1440 NULL, NULL, NULL, NULL);
1441 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1445 edit_deinit(NULL, NULL);
1446 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1450 static void hostapd_cli_cleanup(void)
1452 hostapd_cli_close_connection();
1454 os_daemonize_terminate(pid_file);
1456 os_program_deinit();
1460 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1468 fd = wpa_ctrl_get_fd(ctrl);
1470 while (!hostapd_cli_quit) {
1473 tv.tv_sec = ping_interval;
1475 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1476 if (res < 0 && errno != EINTR) {
1481 if (FD_ISSET(fd, &rfds))
1482 hostapd_cli_recv_pending(ctrl, 0, 1);
1484 len = sizeof(buf) - 1;
1485 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1486 hostapd_cli_action_process) < 0 ||
1487 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1488 printf("hostapd did not reply to PING "
1489 "command - exiting\n");
1497 int main(int argc, char *argv[])
1499 int warning_displayed = 0;
1503 if (os_program_init())
1507 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1512 action_file = optarg;
1518 ping_interval = atoi(optarg);
1524 printf("%s\n", hostapd_cli_version);
1527 os_free(ctrl_ifname);
1528 ctrl_ifname = os_strdup(optarg);
1531 ctrl_iface_dir = optarg;
1537 client_socket_dir = optarg;
1545 interactive = (argc == optind) && (action_file == NULL);
1548 printf("%s\n\n%s\n\n", hostapd_cli_version,
1549 hostapd_cli_license);
1556 if (ctrl_ifname == NULL) {
1557 struct dirent *dent;
1558 DIR *dir = opendir(ctrl_iface_dir);
1560 while ((dent = readdir(dir))) {
1561 if (os_strcmp(dent->d_name, ".") == 0
1563 os_strcmp(dent->d_name, "..") == 0)
1565 printf("Selected interface '%s'\n",
1567 ctrl_ifname = os_strdup(dent->d_name);
1573 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1575 if (warning_displayed)
1576 printf("Connection established.\n");
1581 perror("Failed to connect to hostapd - "
1586 if (!warning_displayed) {
1587 printf("Could not connect to hostapd - re-trying\n");
1588 warning_displayed = 1;
1594 if (interactive || action_file) {
1595 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1596 hostapd_cli_attached = 1;
1598 printf("Warning: Failed to attach to hostapd.\n");
1604 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1608 hostapd_cli_interactive();
1609 else if (action_file)
1610 hostapd_cli_action(ctrl_conn);
1612 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1614 os_free(ctrl_ifname);
1616 hostapd_cli_cleanup();
1620 #else /* CONFIG_NO_CTRL_IFACE */
1622 int main(int argc, char *argv[])
1627 #endif /* CONFIG_NO_CTRL_IFACE */