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 static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
1224 return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
1228 struct hostapd_cli_cmd {
1230 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1231 char ** (*completion)(const char *str, int pos);
1235 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1236 { "ping", hostapd_cli_cmd_ping, NULL,
1237 "= pings hostapd" },
1238 { "mib", hostapd_cli_cmd_mib, NULL,
1239 "= get MIB variables (dot1x, dot11, radius)" },
1240 { "relog", hostapd_cli_cmd_relog, NULL, NULL },
1241 { "status", hostapd_cli_cmd_status, NULL, NULL },
1242 { "sta", hostapd_cli_cmd_sta, NULL,
1243 "<addr> = get MIB variables for one station" },
1244 { "all_sta", hostapd_cli_cmd_all_sta, NULL,
1245 "= get MIB variables for all stations" },
1246 { "new_sta", hostapd_cli_cmd_new_sta, NULL,
1247 "<addr> = add a new station" },
1248 { "deauthenticate", hostapd_cli_cmd_deauthenticate, NULL,
1249 "<addr> = deauthenticate a station" },
1250 { "disassociate", hostapd_cli_cmd_disassociate, NULL,
1251 "<addr> = disassociate a station" },
1252 #ifdef CONFIG_IEEE80211W
1253 { "sa_query", hostapd_cli_cmd_sa_query, NULL,
1254 "<addr> = send SA Query to a station" },
1255 #endif /* CONFIG_IEEE80211W */
1257 { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
1258 "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
1259 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
1260 "<PIN> = verify PIN checksum" },
1261 { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
1262 "= indicate button pushed to initiate PBC" },
1263 { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
1264 "= cancel the pending WPS operation" },
1265 #ifdef CONFIG_WPS_NFC
1266 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
1267 "<hexdump> = report read NFC tag with WPS data" },
1268 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
1269 "<WPS/NDEF> = build NFC configuration token" },
1270 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
1271 "<WPS/NDEF/enable/disable> = manager NFC password token" },
1272 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
1274 #endif /* CONFIG_WPS_NFC */
1275 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
1276 "<cmd> [params..] = enable/disable AP PIN" },
1277 { "wps_config", hostapd_cli_cmd_wps_config, NULL,
1278 "<SSID> <auth> <encr> <key> = configure AP" },
1279 { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
1280 "= show current WPS status" },
1281 #endif /* CONFIG_WPS */
1282 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
1283 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
1284 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
1285 { "get_config", hostapd_cli_cmd_get_config, NULL,
1286 "= show current configuration" },
1287 { "help", hostapd_cli_cmd_help, NULL,
1288 "= show this usage help" },
1289 { "interface", hostapd_cli_cmd_interface, NULL,
1290 "[ifname] = show interfaces/select interface" },
1292 { "fst", hostapd_cli_cmd_fst, NULL, NULL },
1293 #endif /* CONFIG_FST */
1294 { "raw", hostapd_cli_cmd_raw, NULL, NULL },
1295 { "level", hostapd_cli_cmd_level, NULL,
1296 "<debug level> = change debug level" },
1297 { "license", hostapd_cli_cmd_license, NULL,
1298 "= show full hostapd_cli license" },
1299 { "quit", hostapd_cli_cmd_quit, NULL,
1300 "= exit hostapd_cli" },
1301 { "set", hostapd_cli_cmd_set, NULL, NULL },
1302 { "get", hostapd_cli_cmd_get, NULL, NULL },
1303 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
1304 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
1305 { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
1306 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
1307 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
1308 { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
1309 { "enable", hostapd_cli_cmd_enable, NULL, NULL },
1310 { "reload", hostapd_cli_cmd_reload, NULL, NULL },
1311 { "disable", hostapd_cli_cmd_disable, NULL, NULL },
1312 { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
1313 { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
1314 { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
1315 { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
1316 { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
1317 { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
1318 { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
1319 { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
1320 { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
1321 { NULL, NULL, NULL, NULL }
1325 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1327 const struct hostapd_cli_cmd *cmd, *match = NULL;
1331 cmd = hostapd_cli_commands;
1333 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1335 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1336 /* we have an exact match */
1346 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1347 cmd = hostapd_cli_commands;
1349 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1351 printf(" %s", cmd->cmd);
1356 } else if (count == 0) {
1357 printf("Unknown command '%s'\n", argv[0]);
1359 match->handler(ctrl, argc - 1, &argv[1]);
1364 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1368 if (ctrl_conn == NULL)
1370 while (wpa_ctrl_pending(ctrl)) {
1372 size_t len = sizeof(buf) - 1;
1373 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1376 hostapd_cli_action_process(buf, len);
1378 if (in_read && first)
1381 printf("%s\n", buf);
1384 printf("Could not read pending message.\n");
1393 static int tokenize_cmd(char *cmd, char *argv[])
1406 if (argc == max_args)
1409 char *pos2 = os_strrchr(pos, '"');
1413 while (*pos != '\0' && *pos != ' ')
1423 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1425 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1426 printf("Connection to hostapd lost - trying to reconnect\n");
1427 hostapd_cli_close_connection();
1430 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1432 printf("Connection to hostapd re-established\n");
1433 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1434 hostapd_cli_attached = 1;
1436 printf("Warning: Failed to attach to "
1442 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1443 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1447 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1453 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1455 char *argv[max_args];
1457 argc = tokenize_cmd(cmd, argv);
1459 wpa_request(ctrl_conn, argc, argv);
1463 static void hostapd_cli_edit_eof_cb(void *ctx)
1469 static char ** list_cmd_list(void)
1474 count = ARRAY_SIZE(hostapd_cli_commands);
1475 res = os_calloc(count + 1, sizeof(char *));
1479 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1480 res[i] = os_strdup(hostapd_cli_commands[i].cmd);
1489 static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
1494 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1495 if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
1497 if (hostapd_cli_commands[i].completion)
1498 return hostapd_cli_commands[i].completion(str, pos);
1499 if (!hostapd_cli_commands[i].usage)
1502 printf("\r%s\n", hostapd_cli_commands[i].usage);
1511 static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
1518 end = os_strchr(str, ' ');
1519 if (end == NULL || str + pos < end)
1520 return list_cmd_list();
1522 cmd = os_malloc(pos + 1);
1525 os_memcpy(cmd, str, pos);
1526 cmd[end - str] = '\0';
1527 res = hostapd_cli_cmd_completion(cmd, str, pos);
1533 static void hostapd_cli_interactive(void)
1535 printf("\nInteractive mode\n\n");
1537 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1538 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1539 hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
1540 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1544 edit_deinit(NULL, NULL);
1545 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1549 static void hostapd_cli_cleanup(void)
1551 hostapd_cli_close_connection();
1553 os_daemonize_terminate(pid_file);
1555 os_program_deinit();
1559 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1567 fd = wpa_ctrl_get_fd(ctrl);
1569 while (!hostapd_cli_quit) {
1572 tv.tv_sec = ping_interval;
1574 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1575 if (res < 0 && errno != EINTR) {
1580 if (FD_ISSET(fd, &rfds))
1581 hostapd_cli_recv_pending(ctrl, 0, 1);
1583 len = sizeof(buf) - 1;
1584 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1585 hostapd_cli_action_process) < 0 ||
1586 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1587 printf("hostapd did not reply to PING "
1588 "command - exiting\n");
1596 int main(int argc, char *argv[])
1598 int warning_displayed = 0;
1602 if (os_program_init())
1606 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1611 action_file = optarg;
1617 ping_interval = atoi(optarg);
1623 printf("%s\n", hostapd_cli_version);
1626 os_free(ctrl_ifname);
1627 ctrl_ifname = os_strdup(optarg);
1630 ctrl_iface_dir = optarg;
1636 client_socket_dir = optarg;
1644 interactive = (argc == optind) && (action_file == NULL);
1647 printf("%s\n\n%s\n\n", hostapd_cli_version,
1648 hostapd_cli_license);
1655 if (ctrl_ifname == NULL) {
1656 struct dirent *dent;
1657 DIR *dir = opendir(ctrl_iface_dir);
1659 while ((dent = readdir(dir))) {
1660 if (os_strcmp(dent->d_name, ".") == 0
1662 os_strcmp(dent->d_name, "..") == 0)
1664 printf("Selected interface '%s'\n",
1666 ctrl_ifname = os_strdup(dent->d_name);
1672 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1674 if (warning_displayed)
1675 printf("Connection established.\n");
1680 perror("Failed to connect to hostapd - "
1685 if (!warning_displayed) {
1686 printf("Could not connect to hostapd - re-trying\n");
1687 warning_displayed = 1;
1693 if (interactive || action_file) {
1694 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1695 hostapd_cli_attached = 1;
1697 printf("Warning: Failed to attach to hostapd.\n");
1703 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1707 hostapd_cli_interactive();
1708 else if (action_file)
1709 hostapd_cli_action(ctrl_conn);
1711 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1713 os_free(ctrl_ifname);
1715 hostapd_cli_cleanup();
1719 #else /* CONFIG_NO_CTRL_IFACE */
1721 int main(int argc, char *argv[])
1726 #endif /* CONFIG_NO_CTRL_IFACE */