2 * hostapd - command line interface for hostapd daemon
3 * Copyright (c) 2004-2015, 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"
20 static const char *const hostapd_cli_version =
21 "hostapd_cli v" VERSION_STR "\n"
22 "Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
25 static const char *const hostapd_cli_license =
26 "This software may be distributed under the terms of the BSD license.\n"
27 "See README for more details.\n";
29 static const char *const hostapd_cli_full_license =
30 "This software may be distributed under the terms of the BSD license.\n"
32 "Redistribution and use in source and binary forms, with or without\n"
33 "modification, are permitted provided that the following conditions are\n"
36 "1. Redistributions of source code must retain the above copyright\n"
37 " notice, this list of conditions and the following disclaimer.\n"
39 "2. Redistributions in binary form must reproduce the above copyright\n"
40 " notice, this list of conditions and the following disclaimer in the\n"
41 " documentation and/or other materials provided with the distribution.\n"
43 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
44 " names of its contributors may be used to endorse or promote products\n"
45 " derived from this software without specific prior written permission.\n"
47 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
48 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
49 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
50 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
51 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
52 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
53 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
54 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
55 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
56 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
57 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
60 static const char *const commands_help =
62 " mib get MIB variables (dot1x, dot11, radius)\n"
63 " sta <addr> get MIB variables for one station\n"
64 " all_sta get MIB variables for all stations\n"
65 " new_sta <addr> add a new station\n"
66 " deauthenticate <addr> deauthenticate a station\n"
67 " disassociate <addr> disassociate a station\n"
68 #ifdef CONFIG_IEEE80211W
69 " sa_query <addr> send SA Query to a station\n"
70 #endif /* CONFIG_IEEE80211W */
72 " wps_pin <uuid> <pin> [timeout] [addr] add WPS Enrollee PIN\n"
73 " wps_check_pin <PIN> verify PIN checksum\n"
74 " wps_pbc indicate button pushed to initiate PBC\n"
75 " wps_cancel cancel the pending WPS operation\n"
77 " wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
78 " wps_nfc_config_token <WPS/NDEF> build NFC configuration token\n"
79 " wps_nfc_token <WPS/NDEF/enable/disable> manager NFC password token\n"
80 #endif /* CONFIG_WPS_NFC */
81 " wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
82 " wps_config <SSID> <auth> <encr> <key> configure AP\n"
83 " wps_get_status show current WPS status\n"
84 #endif /* CONFIG_WPS */
85 " get_config show current configuration\n"
86 " help show this usage help\n"
87 " interface [ifname] show interfaces/select interface\n"
88 " level <debug level> change debug level\n"
89 " license show full hostapd_cli license\n"
90 " quit exit hostapd_cli\n";
92 static struct wpa_ctrl *ctrl_conn;
93 static int hostapd_cli_quit = 0;
94 static int hostapd_cli_attached = 0;
96 #ifndef CONFIG_CTRL_IFACE_DIR
97 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
98 #endif /* CONFIG_CTRL_IFACE_DIR */
99 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
101 static char *ctrl_ifname = NULL;
102 static const char *pid_file = NULL;
103 static const char *action_file = NULL;
104 static int ping_interval = 5;
105 static int interactive = 0;
108 static void usage(void)
110 fprintf(stderr, "%s\n", hostapd_cli_version);
113 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
115 " [-P<pid file>] [-G<ping interval>] [command..]\n"
118 " -h help (show this usage text)\n"
119 " -v shown version information\n"
120 " -p<path> path to find control sockets (default: "
121 "/var/run/hostapd)\n"
122 " -a<file> run in daemon mode executing the action file "
125 " -B run a daemon in the background\n"
126 " -i<ifname> Interface to listen on (default: first "
127 "interface found in the\n"
134 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
142 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
143 cfile = malloc(flen);
146 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
148 ctrl_conn = wpa_ctrl_open(cfile);
154 static void hostapd_cli_close_connection(void)
156 if (ctrl_conn == NULL)
159 if (hostapd_cli_attached) {
160 wpa_ctrl_detach(ctrl_conn);
161 hostapd_cli_attached = 0;
163 wpa_ctrl_close(ctrl_conn);
168 static void hostapd_cli_msg_cb(char *msg, size_t len)
174 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
180 if (ctrl_conn == NULL) {
181 printf("Not connected to hostapd - command dropped.\n");
184 len = sizeof(buf) - 1;
185 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
188 printf("'%s' command timed out.\n", cmd);
190 } else if (ret < 0) {
191 printf("'%s' command failed.\n", cmd);
202 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
204 return _wpa_ctrl_command(ctrl, cmd, 1);
208 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
210 return wpa_ctrl_command(ctrl, "PING");
214 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
216 return wpa_ctrl_command(ctrl, "RELOG");
220 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
222 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
223 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
224 return wpa_ctrl_command(ctrl, "STATUS");
228 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
232 os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
233 return wpa_ctrl_command(ctrl, buf);
235 return wpa_ctrl_command(ctrl, "MIB");
239 static int hostapd_cli_exec(const char *program, const char *arg1,
246 len = os_strlen(arg1) + os_strlen(arg2) + 2;
247 arg = os_malloc(len);
250 os_snprintf(arg, len, "%s %s", arg1, arg2);
251 res = os_exec(program, arg, 1);
258 static void hostapd_cli_action_process(char *msg, size_t len)
264 pos = os_strchr(pos, '>');
271 hostapd_cli_exec(action_file, ctrl_ifname, pos);
275 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
279 printf("Invalid 'sta' command - at least one argument, STA "
280 "address, is required.\n");
284 snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
286 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
287 return wpa_ctrl_command(ctrl, buf);
291 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
296 printf("Invalid 'new_sta' command - exactly one argument, STA "
297 "address, is required.\n");
300 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
301 return wpa_ctrl_command(ctrl, buf);
305 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
310 printf("Invalid 'deauthenticate' command - exactly one "
311 "argument, STA address, is required.\n");
315 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
318 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
319 return wpa_ctrl_command(ctrl, buf);
323 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
328 printf("Invalid 'disassociate' command - exactly one "
329 "argument, STA address, is required.\n");
333 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
336 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
337 return wpa_ctrl_command(ctrl, buf);
341 #ifdef CONFIG_IEEE80211W
342 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
347 printf("Invalid 'sa_query' command - exactly one argument, "
348 "STA address, is required.\n");
351 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
352 return wpa_ctrl_command(ctrl, buf);
354 #endif /* CONFIG_IEEE80211W */
358 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
363 printf("Invalid 'wps_pin' command - at least two arguments, "
364 "UUID and PIN, are required.\n");
368 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
369 argv[0], argv[1], argv[2], argv[3]);
371 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
372 argv[0], argv[1], argv[2]);
374 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
375 return wpa_ctrl_command(ctrl, buf);
379 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
385 if (argc != 1 && argc != 2) {
386 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
387 "- PIN to be verified\n");
392 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
395 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
397 if (os_snprintf_error(sizeof(cmd), res)) {
398 printf("Too long WPS_CHECK_PIN command.\n");
401 return wpa_ctrl_command(ctrl, cmd);
405 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
408 return wpa_ctrl_command(ctrl, "WPS_PBC");
412 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
415 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
419 #ifdef CONFIG_WPS_NFC
420 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
428 printf("Invalid 'wps_nfc_tag_read' command - one argument "
433 buflen = 18 + os_strlen(argv[0]);
434 buf = os_malloc(buflen);
437 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
439 ret = wpa_ctrl_command(ctrl, buf);
446 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
447 int argc, char *argv[])
453 printf("Invalid 'wps_nfc_config_token' command - one argument "
458 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
460 if (os_snprintf_error(sizeof(cmd), res)) {
461 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
464 return wpa_ctrl_command(ctrl, cmd);
468 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
469 int argc, char *argv[])
475 printf("Invalid 'wps_nfc_token' command - one argument is "
480 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
481 if (os_snprintf_error(sizeof(cmd), res)) {
482 printf("Too long WPS_NFC_TOKEN command.\n");
485 return wpa_ctrl_command(ctrl, cmd);
489 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
490 int argc, char *argv[])
496 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
501 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
503 if (os_snprintf_error(sizeof(cmd), res)) {
504 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
507 return wpa_ctrl_command(ctrl, cmd);
510 #endif /* CONFIG_WPS_NFC */
513 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
518 printf("Invalid 'wps_ap_pin' command - at least one argument "
523 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
524 argv[0], argv[1], argv[2]);
526 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
529 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
530 return wpa_ctrl_command(ctrl, buf);
534 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
537 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
541 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
545 char ssid_hex[2 * SSID_MAX_LEN + 1];
546 char key_hex[2 * 64 + 1];
550 printf("Invalid 'wps_config' command - at least two arguments "
556 for (i = 0; i < SSID_MAX_LEN; i++) {
557 if (argv[0][i] == '\0')
559 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
564 for (i = 0; i < 64; i++) {
565 if (argv[3][i] == '\0')
567 os_snprintf(&key_hex[i * 2], 3, "%02x",
573 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
574 ssid_hex, argv[1], argv[2], key_hex);
576 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
577 ssid_hex, argv[1], argv[2]);
579 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
581 return wpa_ctrl_command(ctrl, buf);
583 #endif /* CONFIG_WPS */
586 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
593 printf("Invalid 'disassoc_imminent' command - two arguments "
594 "(STA addr and Disassociation Timer) are needed\n");
598 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
600 if (os_snprintf_error(sizeof(buf), res))
602 return wpa_ctrl_command(ctrl, buf);
606 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
613 printf("Invalid 'ess_disassoc' command - three arguments (STA "
614 "addr, disassoc timer, and URL) are needed\n");
618 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
619 argv[0], argv[1], argv[2]);
620 if (os_snprintf_error(sizeof(buf), res))
622 return wpa_ctrl_command(ctrl, buf);
626 static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
629 char buf[2000], *tmp;
633 printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
637 res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
638 if (os_snprintf_error(sizeof(buf), res))
642 for (i = 1; i < argc; i++) {
644 res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
645 if (os_snprintf_error(sizeof(buf) - total, res))
649 return wpa_ctrl_command(ctrl, buf);
653 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
656 return wpa_ctrl_command(ctrl, "GET_CONFIG");
660 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
661 char *addr, size_t addr_len)
663 char buf[4096], *pos;
667 if (ctrl_conn == NULL) {
668 printf("Not connected to hostapd - command dropped.\n");
671 len = sizeof(buf) - 1;
672 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
675 printf("'%s' command timed out.\n", cmd);
677 } else if (ret < 0) {
678 printf("'%s' command failed.\n", cmd);
683 if (memcmp(buf, "FAIL", 4) == 0)
688 while (*pos != '\0' && *pos != '\n')
691 os_strlcpy(addr, buf, addr_len);
696 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
699 char addr[32], cmd[64];
701 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
704 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
705 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
711 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
713 printf("%s", commands_help);
718 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
721 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
726 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
727 int argc, char *argv[])
733 printf("Invalid 'set_qos_map_set' command - "
734 "one argument (comma delimited QoS map set) "
739 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
740 if (os_snprintf_error(sizeof(buf), res))
742 return wpa_ctrl_command(ctrl, buf);
746 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
747 int argc, char *argv[])
753 printf("Invalid 'send_qos_map_conf' command - "
754 "one argument (STA addr) is needed\n");
758 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
759 if (os_snprintf_error(sizeof(buf), res))
761 return wpa_ctrl_command(ctrl, buf);
765 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
772 printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
773 "addr and URL) are needed\n");
777 res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
779 if (os_snprintf_error(sizeof(buf), res))
781 return wpa_ctrl_command(ctrl, buf);
785 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
792 printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
797 res = os_snprintf(buf, sizeof(buf),
798 "HS20_DEAUTH_REQ %s %s %s %s",
799 argv[0], argv[1], argv[2], argv[3]);
801 res = os_snprintf(buf, sizeof(buf),
802 "HS20_DEAUTH_REQ %s %s %s",
803 argv[0], argv[1], argv[2]);
804 if (os_snprintf_error(sizeof(buf), res))
806 return wpa_ctrl_command(ctrl, buf);
810 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
812 hostapd_cli_quit = 1;
819 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
823 printf("Invalid LEVEL command: needs one argument (debug "
827 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
828 return wpa_ctrl_command(ctrl, cmd);
832 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
837 dir = opendir(ctrl_iface_dir);
839 printf("Control interface directory '%s' could not be "
840 "openned.\n", ctrl_iface_dir);
844 printf("Available interfaces:\n");
845 while ((dent = readdir(dir))) {
846 if (strcmp(dent->d_name, ".") == 0 ||
847 strcmp(dent->d_name, "..") == 0)
849 printf("%s\n", dent->d_name);
855 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
859 hostapd_cli_list_interfaces(ctrl);
863 hostapd_cli_close_connection();
864 os_free(ctrl_ifname);
865 ctrl_ifname = os_strdup(argv[0]);
866 if (ctrl_ifname == NULL)
869 if (hostapd_cli_open_connection(ctrl_ifname)) {
870 printf("Connected to interface '%s.\n", ctrl_ifname);
871 if (wpa_ctrl_attach(ctrl_conn) == 0) {
872 hostapd_cli_attached = 1;
874 printf("Warning: Failed to attach to "
878 printf("Could not connect to interface '%s' - re-trying\n",
885 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
891 printf("Invalid SET command: needs two arguments (variable "
892 "name and value)\n");
896 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
897 if (os_snprintf_error(sizeof(cmd), res)) {
898 printf("Too long SET command.\n");
901 return wpa_ctrl_command(ctrl, cmd);
905 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
911 printf("Invalid GET command: needs one argument (variable "
916 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
917 if (os_snprintf_error(sizeof(cmd), res)) {
918 printf("Too long GET command.\n");
921 return wpa_ctrl_command(ctrl, cmd);
926 static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
934 printf("FST command: parameters are required.\n");
938 total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
940 for (i = 0; i < argc; i++) {
941 res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
943 if (os_snprintf_error(sizeof(cmd) - total, res)) {
944 printf("Too long fst command.\n");
949 return wpa_ctrl_command(ctrl, cmd);
951 #endif /* CONFIG_FST */
954 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
955 int argc, char *argv[])
964 printf("Invalid chan_switch command: needs at least two "
965 "arguments (count and freq)\n"
966 "usage: <cs_count> <freq> [sec_channel_offset=] "
967 "[center_freq1=] [center_freq2=] [bandwidth=] "
968 "[blocktx] [ht|vht]\n");
972 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
974 if (os_snprintf_error(sizeof(cmd), res)) {
975 printf("Too long CHAN_SWITCH command.\n");
980 for (i = 2; i < argc; i++) {
982 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
983 if (os_snprintf_error(sizeof(cmd) - total, res)) {
984 printf("Too long CHAN_SWITCH command.\n");
989 return wpa_ctrl_command(ctrl, cmd);
993 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
996 return wpa_ctrl_command(ctrl, "ENABLE");
1000 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
1003 return wpa_ctrl_command(ctrl, "RELOAD");
1007 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
1010 return wpa_ctrl_command(ctrl, "DISABLE");
1014 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
1019 if (argc < 2 || argc > 3) {
1020 printf("Invalid vendor command\n"
1021 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
1025 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
1026 argc == 3 ? argv[2] : "");
1027 if (os_snprintf_error(sizeof(cmd), res)) {
1028 printf("Too long VENDOR command.\n");
1031 return wpa_ctrl_command(ctrl, cmd);
1035 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1038 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1042 static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
1048 res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
1049 argc >= 1 ? " " : "",
1050 argc >= 1 ? argv[0] : "",
1051 argc == 2 ? " " : "",
1052 argc == 2 ? argv[1] : "");
1053 if (os_snprintf_error(sizeof(cmd), res)) {
1054 printf("Too long option\n");
1057 return wpa_ctrl_command(ctrl, cmd);
1061 struct hostapd_cli_cmd {
1063 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1066 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1067 { "ping", hostapd_cli_cmd_ping },
1068 { "mib", hostapd_cli_cmd_mib },
1069 { "relog", hostapd_cli_cmd_relog },
1070 { "status", hostapd_cli_cmd_status },
1071 { "sta", hostapd_cli_cmd_sta },
1072 { "all_sta", hostapd_cli_cmd_all_sta },
1073 { "new_sta", hostapd_cli_cmd_new_sta },
1074 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
1075 { "disassociate", hostapd_cli_cmd_disassociate },
1076 #ifdef CONFIG_IEEE80211W
1077 { "sa_query", hostapd_cli_cmd_sa_query },
1078 #endif /* CONFIG_IEEE80211W */
1080 { "wps_pin", hostapd_cli_cmd_wps_pin },
1081 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
1082 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
1083 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
1084 #ifdef CONFIG_WPS_NFC
1085 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
1086 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
1087 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
1088 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
1089 #endif /* CONFIG_WPS_NFC */
1090 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
1091 { "wps_config", hostapd_cli_cmd_wps_config },
1092 { "wps_get_status", hostapd_cli_cmd_wps_get_status },
1093 #endif /* CONFIG_WPS */
1094 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
1095 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
1096 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
1097 { "get_config", hostapd_cli_cmd_get_config },
1098 { "help", hostapd_cli_cmd_help },
1099 { "interface", hostapd_cli_cmd_interface },
1101 { "fst", hostapd_cli_cmd_fst },
1102 #endif /* CONFIG_FST */
1103 { "level", hostapd_cli_cmd_level },
1104 { "license", hostapd_cli_cmd_license },
1105 { "quit", hostapd_cli_cmd_quit },
1106 { "set", hostapd_cli_cmd_set },
1107 { "get", hostapd_cli_cmd_get },
1108 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
1109 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
1110 { "chan_switch", hostapd_cli_cmd_chan_switch },
1111 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
1112 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
1113 { "vendor", hostapd_cli_cmd_vendor },
1114 { "enable", hostapd_cli_cmd_enable },
1115 { "reload", hostapd_cli_cmd_reload },
1116 { "disable", hostapd_cli_cmd_disable },
1117 { "erp_flush", hostapd_cli_cmd_erp_flush },
1118 { "log_level", hostapd_cli_cmd_log_level },
1123 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1125 const struct hostapd_cli_cmd *cmd, *match = NULL;
1129 cmd = hostapd_cli_commands;
1131 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1133 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1134 /* we have an exact match */
1144 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1145 cmd = hostapd_cli_commands;
1147 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1149 printf(" %s", cmd->cmd);
1154 } else if (count == 0) {
1155 printf("Unknown command '%s'\n", argv[0]);
1157 match->handler(ctrl, argc - 1, &argv[1]);
1162 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1166 if (ctrl_conn == NULL)
1168 while (wpa_ctrl_pending(ctrl)) {
1170 size_t len = sizeof(buf) - 1;
1171 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1174 hostapd_cli_action_process(buf, len);
1176 if (in_read && first)
1179 printf("%s\n", buf);
1182 printf("Could not read pending message.\n");
1191 static int tokenize_cmd(char *cmd, char *argv[])
1204 if (argc == max_args)
1207 char *pos2 = os_strrchr(pos, '"');
1211 while (*pos != '\0' && *pos != ' ')
1221 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1223 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1224 printf("Connection to hostapd lost - trying to reconnect\n");
1225 hostapd_cli_close_connection();
1228 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1230 printf("Connection to hostapd re-established\n");
1231 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1232 hostapd_cli_attached = 1;
1234 printf("Warning: Failed to attach to "
1240 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1241 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1245 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1251 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1253 char *argv[max_args];
1255 argc = tokenize_cmd(cmd, argv);
1257 wpa_request(ctrl_conn, argc, argv);
1261 static void hostapd_cli_edit_eof_cb(void *ctx)
1267 static void hostapd_cli_interactive(void)
1269 printf("\nInteractive mode\n\n");
1271 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1272 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1273 NULL, NULL, NULL, NULL);
1274 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1278 edit_deinit(NULL, NULL);
1279 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1283 static void hostapd_cli_cleanup(void)
1285 hostapd_cli_close_connection();
1287 os_daemonize_terminate(pid_file);
1289 os_program_deinit();
1293 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1301 fd = wpa_ctrl_get_fd(ctrl);
1303 while (!hostapd_cli_quit) {
1306 tv.tv_sec = ping_interval;
1308 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1309 if (res < 0 && errno != EINTR) {
1314 if (FD_ISSET(fd, &rfds))
1315 hostapd_cli_recv_pending(ctrl, 0, 1);
1317 len = sizeof(buf) - 1;
1318 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1319 hostapd_cli_action_process) < 0 ||
1320 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1321 printf("hostapd did not reply to PING "
1322 "command - exiting\n");
1330 int main(int argc, char *argv[])
1332 int warning_displayed = 0;
1336 if (os_program_init())
1340 c = getopt(argc, argv, "a:BhG:i:p:P:v");
1345 action_file = optarg;
1351 ping_interval = atoi(optarg);
1357 printf("%s\n", hostapd_cli_version);
1360 os_free(ctrl_ifname);
1361 ctrl_ifname = os_strdup(optarg);
1364 ctrl_iface_dir = optarg;
1375 interactive = (argc == optind) && (action_file == NULL);
1378 printf("%s\n\n%s\n\n", hostapd_cli_version,
1379 hostapd_cli_license);
1386 if (ctrl_ifname == NULL) {
1387 struct dirent *dent;
1388 DIR *dir = opendir(ctrl_iface_dir);
1390 while ((dent = readdir(dir))) {
1391 if (os_strcmp(dent->d_name, ".") == 0
1393 os_strcmp(dent->d_name, "..") == 0)
1395 printf("Selected interface '%s'\n",
1397 ctrl_ifname = os_strdup(dent->d_name);
1403 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1405 if (warning_displayed)
1406 printf("Connection established.\n");
1411 perror("Failed to connect to hostapd - "
1416 if (!warning_displayed) {
1417 printf("Could not connect to hostapd - re-trying\n");
1418 warning_displayed = 1;
1424 if (interactive || action_file) {
1425 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1426 hostapd_cli_attached = 1;
1428 printf("Warning: Failed to attach to hostapd.\n");
1434 if (daemonize && os_daemonize(pid_file))
1438 hostapd_cli_interactive();
1439 else if (action_file)
1440 hostapd_cli_action(ctrl_conn);
1442 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1444 os_free(ctrl_ifname);
1446 hostapd_cli_cleanup();