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 struct wpa_ctrl *ctrl_conn;
62 static int hostapd_cli_quit = 0;
63 static int hostapd_cli_attached = 0;
65 #ifndef CONFIG_CTRL_IFACE_DIR
66 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
67 #endif /* CONFIG_CTRL_IFACE_DIR */
68 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
69 static const char *client_socket_dir = NULL;
71 static char *ctrl_ifname = NULL;
72 static const char *pid_file = NULL;
73 static const char *action_file = NULL;
74 static int ping_interval = 5;
75 static int interactive = 0;
77 static void print_help(FILE *stream, const char *cmd);
80 static void usage(void)
82 fprintf(stderr, "%s\n", hostapd_cli_version);
85 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
87 " [-P<pid file>] [-G<ping interval>] [command..]\n"
90 " -h help (show this usage text)\n"
91 " -v shown version information\n"
92 " -p<path> path to find control sockets (default: "
94 " -s<dir_path> dir path to open client sockets (default: "
95 CONFIG_CTRL_IFACE_DIR ")\n"
96 " -a<file> run in daemon mode executing the action file "
99 " -B run a daemon in the background\n"
100 " -i<ifname> Interface to listen on (default: first "
101 "interface found in the\n"
102 " socket path)\n\n");
103 print_help(stderr, NULL);
107 static int str_starts(const char *src, const char *match)
109 return os_strncmp(src, match, os_strlen(match)) == 0;
113 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
115 #ifndef CONFIG_CTRL_IFACE_UDP
118 #endif /* !CONFIG_CTRL_IFACE_UDP */
123 #ifdef CONFIG_CTRL_IFACE_UDP
124 ctrl_conn = wpa_ctrl_open(ifname);
126 #else /* CONFIG_CTRL_IFACE_UDP */
127 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
128 cfile = malloc(flen);
131 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
133 if (client_socket_dir && client_socket_dir[0] &&
134 access(client_socket_dir, F_OK) < 0) {
135 perror(client_socket_dir);
140 ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
143 #endif /* CONFIG_CTRL_IFACE_UDP */
147 static void hostapd_cli_close_connection(void)
149 if (ctrl_conn == NULL)
152 if (hostapd_cli_attached) {
153 wpa_ctrl_detach(ctrl_conn);
154 hostapd_cli_attached = 0;
156 wpa_ctrl_close(ctrl_conn);
161 static void hostapd_cli_msg_cb(char *msg, size_t len)
167 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
173 if (ctrl_conn == NULL) {
174 printf("Not connected to hostapd - command dropped.\n");
177 len = sizeof(buf) - 1;
178 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
181 printf("'%s' command timed out.\n", cmd);
183 } else if (ret < 0) {
184 printf("'%s' command failed.\n", cmd);
195 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
197 return _wpa_ctrl_command(ctrl, cmd, 1);
201 static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
210 res = os_snprintf(pos, end - pos, "%s", cmd);
211 if (os_snprintf_error(end - pos, res))
215 for (i = 0; i < argc; i++) {
216 res = os_snprintf(pos, end - pos, " %s", argv[i]);
217 if (os_snprintf_error(end - pos, res))
222 buf[buflen - 1] = '\0';
226 printf("Too long command\n");
231 static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
232 int min_args, int argc, char *argv[])
236 if (argc < min_args) {
237 printf("Invalid %s command - at least %d argument%s required.\n",
238 cmd, min_args, min_args > 1 ? "s are" : " is");
241 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
243 return wpa_ctrl_command(ctrl, buf);
247 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
249 return wpa_ctrl_command(ctrl, "PING");
253 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
255 return wpa_ctrl_command(ctrl, "RELOG");
259 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
261 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
262 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
263 return wpa_ctrl_command(ctrl, "STATUS");
267 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
271 os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
272 return wpa_ctrl_command(ctrl, buf);
274 return wpa_ctrl_command(ctrl, "MIB");
278 static int hostapd_cli_exec(const char *program, const char *arg1,
285 len = os_strlen(arg1) + os_strlen(arg2) + 2;
286 arg = os_malloc(len);
289 os_snprintf(arg, len, "%s %s", arg1, arg2);
290 res = os_exec(program, arg, 1);
297 static void hostapd_cli_action_process(char *msg, size_t len)
303 pos = os_strchr(pos, '>');
310 hostapd_cli_exec(action_file, ctrl_ifname, pos);
314 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
318 printf("Invalid 'sta' command - at least one argument, STA "
319 "address, is required.\n");
323 snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
325 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
326 return wpa_ctrl_command(ctrl, buf);
330 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
335 printf("Invalid 'new_sta' command - exactly one argument, STA "
336 "address, is required.\n");
339 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
340 return wpa_ctrl_command(ctrl, buf);
344 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
349 printf("Invalid 'deauthenticate' command - exactly one "
350 "argument, STA address, is required.\n");
354 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
357 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
358 return wpa_ctrl_command(ctrl, buf);
362 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
367 printf("Invalid 'disassociate' command - exactly one "
368 "argument, STA address, is required.\n");
372 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
375 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
376 return wpa_ctrl_command(ctrl, buf);
380 #ifdef CONFIG_IEEE80211W
381 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
386 printf("Invalid 'sa_query' command - exactly one argument, "
387 "STA address, is required.\n");
390 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
391 return wpa_ctrl_command(ctrl, buf);
393 #endif /* CONFIG_IEEE80211W */
397 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
402 printf("Invalid 'wps_pin' command - at least two arguments, "
403 "UUID and PIN, are required.\n");
407 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
408 argv[0], argv[1], argv[2], argv[3]);
410 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
411 argv[0], argv[1], argv[2]);
413 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
414 return wpa_ctrl_command(ctrl, buf);
418 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
424 if (argc != 1 && argc != 2) {
425 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
426 "- PIN to be verified\n");
431 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
434 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
436 if (os_snprintf_error(sizeof(cmd), res)) {
437 printf("Too long WPS_CHECK_PIN command.\n");
440 return wpa_ctrl_command(ctrl, cmd);
444 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
447 return wpa_ctrl_command(ctrl, "WPS_PBC");
451 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
454 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
458 #ifdef CONFIG_WPS_NFC
459 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
467 printf("Invalid 'wps_nfc_tag_read' command - one argument "
472 buflen = 18 + os_strlen(argv[0]);
473 buf = os_malloc(buflen);
476 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
478 ret = wpa_ctrl_command(ctrl, buf);
485 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
486 int argc, char *argv[])
492 printf("Invalid 'wps_nfc_config_token' command - one argument "
497 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
499 if (os_snprintf_error(sizeof(cmd), res)) {
500 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
503 return wpa_ctrl_command(ctrl, cmd);
507 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
508 int argc, char *argv[])
514 printf("Invalid 'wps_nfc_token' command - one argument is "
519 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
520 if (os_snprintf_error(sizeof(cmd), res)) {
521 printf("Too long WPS_NFC_TOKEN command.\n");
524 return wpa_ctrl_command(ctrl, cmd);
528 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
529 int argc, char *argv[])
535 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
540 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
542 if (os_snprintf_error(sizeof(cmd), res)) {
543 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
546 return wpa_ctrl_command(ctrl, cmd);
549 #endif /* CONFIG_WPS_NFC */
552 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
557 printf("Invalid 'wps_ap_pin' command - at least one argument "
562 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
563 argv[0], argv[1], argv[2]);
565 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
568 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
569 return wpa_ctrl_command(ctrl, buf);
573 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
576 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
580 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
584 char ssid_hex[2 * SSID_MAX_LEN + 1];
585 char key_hex[2 * 64 + 1];
589 printf("Invalid 'wps_config' command - at least two arguments "
595 for (i = 0; i < SSID_MAX_LEN; i++) {
596 if (argv[0][i] == '\0')
598 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
603 for (i = 0; i < 64; i++) {
604 if (argv[3][i] == '\0')
606 os_snprintf(&key_hex[i * 2], 3, "%02x",
612 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
613 ssid_hex, argv[1], argv[2], key_hex);
615 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
616 ssid_hex, argv[1], argv[2]);
618 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
620 return wpa_ctrl_command(ctrl, buf);
622 #endif /* CONFIG_WPS */
625 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
632 printf("Invalid 'disassoc_imminent' command - two arguments "
633 "(STA addr and Disassociation Timer) are needed\n");
637 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
639 if (os_snprintf_error(sizeof(buf), res))
641 return wpa_ctrl_command(ctrl, buf);
645 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
652 printf("Invalid 'ess_disassoc' command - three arguments (STA "
653 "addr, disassoc timer, and URL) are needed\n");
657 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
658 argv[0], argv[1], argv[2]);
659 if (os_snprintf_error(sizeof(buf), res))
661 return wpa_ctrl_command(ctrl, buf);
665 static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
668 char buf[2000], *tmp;
672 printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
676 res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
677 if (os_snprintf_error(sizeof(buf), res))
681 for (i = 1; i < argc; i++) {
683 res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
684 if (os_snprintf_error(sizeof(buf) - total, res))
688 return wpa_ctrl_command(ctrl, buf);
692 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
695 return wpa_ctrl_command(ctrl, "GET_CONFIG");
699 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
700 char *addr, size_t addr_len)
702 char buf[4096], *pos;
706 if (ctrl_conn == NULL) {
707 printf("Not connected to hostapd - command dropped.\n");
710 len = sizeof(buf) - 1;
711 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
714 printf("'%s' command timed out.\n", cmd);
716 } else if (ret < 0) {
717 printf("'%s' command failed.\n", cmd);
722 if (memcmp(buf, "FAIL", 4) == 0)
727 while (*pos != '\0' && *pos != '\n')
730 os_strlcpy(addr, buf, addr_len);
735 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
738 char addr[32], cmd[64];
740 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
743 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
744 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
750 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
752 print_help(stdout, argc > 0 ? argv[0] : NULL);
757 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
760 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
765 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
766 int argc, char *argv[])
772 printf("Invalid 'set_qos_map_set' command - "
773 "one argument (comma delimited QoS map set) "
778 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
779 if (os_snprintf_error(sizeof(buf), res))
781 return wpa_ctrl_command(ctrl, buf);
785 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
786 int argc, char *argv[])
792 printf("Invalid 'send_qos_map_conf' command - "
793 "one argument (STA addr) is needed\n");
797 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
798 if (os_snprintf_error(sizeof(buf), res))
800 return wpa_ctrl_command(ctrl, buf);
804 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
811 printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
812 "addr and URL) are needed\n");
816 res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
818 if (os_snprintf_error(sizeof(buf), res))
820 return wpa_ctrl_command(ctrl, buf);
824 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
831 printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
836 res = os_snprintf(buf, sizeof(buf),
837 "HS20_DEAUTH_REQ %s %s %s %s",
838 argv[0], argv[1], argv[2], argv[3]);
840 res = os_snprintf(buf, sizeof(buf),
841 "HS20_DEAUTH_REQ %s %s %s",
842 argv[0], argv[1], argv[2]);
843 if (os_snprintf_error(sizeof(buf), res))
845 return wpa_ctrl_command(ctrl, buf);
849 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
851 hostapd_cli_quit = 1;
858 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
862 printf("Invalid LEVEL command: needs one argument (debug "
866 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
867 return wpa_ctrl_command(ctrl, cmd);
871 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
876 dir = opendir(ctrl_iface_dir);
878 printf("Control interface directory '%s' could not be "
879 "openned.\n", ctrl_iface_dir);
883 printf("Available interfaces:\n");
884 while ((dent = readdir(dir))) {
885 if (strcmp(dent->d_name, ".") == 0 ||
886 strcmp(dent->d_name, "..") == 0)
888 printf("%s\n", dent->d_name);
894 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
898 hostapd_cli_list_interfaces(ctrl);
902 hostapd_cli_close_connection();
903 os_free(ctrl_ifname);
904 ctrl_ifname = os_strdup(argv[0]);
905 if (ctrl_ifname == NULL)
908 if (hostapd_cli_open_connection(ctrl_ifname)) {
909 printf("Connected to interface '%s.\n", ctrl_ifname);
910 if (wpa_ctrl_attach(ctrl_conn) == 0) {
911 hostapd_cli_attached = 1;
913 printf("Warning: Failed to attach to "
917 printf("Could not connect to interface '%s' - re-trying\n",
924 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
930 printf("Invalid SET command: needs two arguments (variable "
931 "name and value)\n");
935 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
936 if (os_snprintf_error(sizeof(cmd), res)) {
937 printf("Too long SET command.\n");
940 return wpa_ctrl_command(ctrl, cmd);
944 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
950 printf("Invalid GET command: needs one argument (variable "
955 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
956 if (os_snprintf_error(sizeof(cmd), res)) {
957 printf("Too long GET command.\n");
960 return wpa_ctrl_command(ctrl, cmd);
965 static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
973 printf("FST command: parameters are required.\n");
977 total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
979 for (i = 0; i < argc; i++) {
980 res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
982 if (os_snprintf_error(sizeof(cmd) - total, res)) {
983 printf("Too long fst command.\n");
988 return wpa_ctrl_command(ctrl, cmd);
990 #endif /* CONFIG_FST */
993 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
994 int argc, char *argv[])
1003 printf("Invalid chan_switch command: needs at least two "
1004 "arguments (count and freq)\n"
1005 "usage: <cs_count> <freq> [sec_channel_offset=] "
1006 "[center_freq1=] [center_freq2=] [bandwidth=] "
1007 "[blocktx] [ht|vht]\n");
1011 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
1013 if (os_snprintf_error(sizeof(cmd), res)) {
1014 printf("Too long CHAN_SWITCH command.\n");
1019 for (i = 2; i < argc; i++) {
1021 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
1022 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1023 printf("Too long CHAN_SWITCH command.\n");
1028 return wpa_ctrl_command(ctrl, cmd);
1032 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
1035 return wpa_ctrl_command(ctrl, "ENABLE");
1039 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
1042 return wpa_ctrl_command(ctrl, "RELOAD");
1046 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
1049 return wpa_ctrl_command(ctrl, "DISABLE");
1053 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
1058 if (argc < 2 || argc > 3) {
1059 printf("Invalid vendor command\n"
1060 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
1064 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
1065 argc == 3 ? argv[2] : "");
1066 if (os_snprintf_error(sizeof(cmd), res)) {
1067 printf("Too long VENDOR command.\n");
1070 return wpa_ctrl_command(ctrl, cmd);
1074 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1077 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1081 static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
1087 res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
1088 argc >= 1 ? " " : "",
1089 argc >= 1 ? argv[0] : "",
1090 argc == 2 ? " " : "",
1091 argc == 2 ? argv[1] : "");
1092 if (os_snprintf_error(sizeof(cmd), res)) {
1093 printf("Too long option\n");
1096 return wpa_ctrl_command(ctrl, cmd);
1100 static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
1104 return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
1108 static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1110 return wpa_ctrl_command(ctrl, "PMKSA");
1114 static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
1117 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
1121 static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
1127 if (argc < 3 || argc > 5) {
1128 printf("Invalid set_neighbor command: needs 3-5 arguments\n");
1132 res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
1133 argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
1134 argc == 5 ? argv[4] : "");
1135 if (os_snprintf_error(sizeof(cmd), res)) {
1136 printf("Too long SET_NEIGHBOR command.\n");
1139 return wpa_ctrl_command(ctrl, cmd);
1143 static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
1150 printf("Invalid remove_neighbor command: needs 2 arguments\n");
1154 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
1156 if (os_snprintf_error(sizeof(cmd), res)) {
1157 printf("Too long REMOVE_NEIGHBOR command.\n");
1160 return wpa_ctrl_command(ctrl, cmd);
1164 static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
1171 printf("Invalid req_lci command - requires destination address\n");
1175 res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
1176 if (os_snprintf_error(sizeof(cmd), res)) {
1177 printf("Too long REQ_LCI command.\n");
1180 return wpa_ctrl_command(ctrl, cmd);
1184 static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
1188 printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
1192 return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
1196 static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
1199 return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
1203 struct hostapd_cli_cmd {
1205 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1206 char ** (*completion)(const char *str, int pos);
1210 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1211 { "ping", hostapd_cli_cmd_ping, NULL,
1212 "= pings hostapd" },
1213 { "mib", hostapd_cli_cmd_mib, NULL,
1214 "= get MIB variables (dot1x, dot11, radius)" },
1215 { "relog", hostapd_cli_cmd_relog, NULL, NULL },
1216 { "status", hostapd_cli_cmd_status, NULL, NULL },
1217 { "sta", hostapd_cli_cmd_sta, NULL,
1218 "<addr> = get MIB variables for one station" },
1219 { "all_sta", hostapd_cli_cmd_all_sta, NULL,
1220 "= get MIB variables for all stations" },
1221 { "new_sta", hostapd_cli_cmd_new_sta, NULL,
1222 "<addr> = add a new station" },
1223 { "deauthenticate", hostapd_cli_cmd_deauthenticate, NULL,
1224 "<addr> = deauthenticate a station" },
1225 { "disassociate", hostapd_cli_cmd_disassociate, NULL,
1226 "<addr> = disassociate a station" },
1227 #ifdef CONFIG_IEEE80211W
1228 { "sa_query", hostapd_cli_cmd_sa_query, NULL,
1229 "<addr> = send SA Query to a station" },
1230 #endif /* CONFIG_IEEE80211W */
1232 { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
1233 "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
1234 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
1235 "<PIN> = verify PIN checksum" },
1236 { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
1237 "= indicate button pushed to initiate PBC" },
1238 { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
1239 "= cancel the pending WPS operation" },
1240 #ifdef CONFIG_WPS_NFC
1241 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
1242 "<hexdump> = report read NFC tag with WPS data" },
1243 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
1244 "<WPS/NDEF> = build NFC configuration token" },
1245 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
1246 "<WPS/NDEF/enable/disable> = manager NFC password token" },
1247 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
1249 #endif /* CONFIG_WPS_NFC */
1250 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
1251 "<cmd> [params..] = enable/disable AP PIN" },
1252 { "wps_config", hostapd_cli_cmd_wps_config, NULL,
1253 "<SSID> <auth> <encr> <key> = configure AP" },
1254 { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
1255 "= show current WPS status" },
1256 #endif /* CONFIG_WPS */
1257 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
1258 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
1259 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
1260 { "get_config", hostapd_cli_cmd_get_config, NULL,
1261 "= show current configuration" },
1262 { "help", hostapd_cli_cmd_help, NULL,
1263 "= show this usage help" },
1264 { "interface", hostapd_cli_cmd_interface, NULL,
1265 "[ifname] = show interfaces/select interface" },
1267 { "fst", hostapd_cli_cmd_fst, NULL, NULL },
1268 #endif /* CONFIG_FST */
1269 { "raw", hostapd_cli_cmd_raw, NULL, NULL },
1270 { "level", hostapd_cli_cmd_level, NULL,
1271 "<debug level> = change debug level" },
1272 { "license", hostapd_cli_cmd_license, NULL,
1273 "= show full hostapd_cli license" },
1274 { "quit", hostapd_cli_cmd_quit, NULL,
1275 "= exit hostapd_cli" },
1276 { "set", hostapd_cli_cmd_set, NULL, NULL },
1277 { "get", hostapd_cli_cmd_get, NULL, NULL },
1278 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
1279 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
1280 { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
1281 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
1282 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
1283 { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
1284 { "enable", hostapd_cli_cmd_enable, NULL, NULL },
1285 { "reload", hostapd_cli_cmd_reload, NULL, NULL },
1286 { "disable", hostapd_cli_cmd_disable, NULL, NULL },
1287 { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
1288 { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
1289 { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
1290 { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
1291 { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
1292 { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
1293 { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
1294 { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
1295 { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
1296 { NULL, NULL, NULL, NULL }
1301 * Prints command usage, lines are padded with the specified string.
1303 static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
1309 if (cmd->usage == NULL)
1311 fprintf(stream, "%s%s ", pad, cmd->cmd);
1312 for (n = 0; (c = cmd->usage[n]); n++) {
1313 fprintf(stream, "%c", c);
1315 fprintf(stream, "%s", pad);
1317 fprintf(stream, "\n");
1321 static void print_help(FILE *stream, const char *cmd)
1325 fprintf(stream, "commands:\n");
1326 for (n = 0; hostapd_cli_commands[n].cmd; n++) {
1327 if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
1328 print_cmd_help(stream, &hostapd_cli_commands[n], " ");
1333 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1335 const struct hostapd_cli_cmd *cmd, *match = NULL;
1339 cmd = hostapd_cli_commands;
1341 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1343 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1344 /* we have an exact match */
1354 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1355 cmd = hostapd_cli_commands;
1357 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1359 printf(" %s", cmd->cmd);
1364 } else if (count == 0) {
1365 printf("Unknown command '%s'\n", argv[0]);
1367 match->handler(ctrl, argc - 1, &argv[1]);
1372 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1376 if (ctrl_conn == NULL)
1378 while (wpa_ctrl_pending(ctrl)) {
1380 size_t len = sizeof(buf) - 1;
1381 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1384 hostapd_cli_action_process(buf, len);
1386 if (in_read && first)
1389 printf("%s\n", buf);
1392 printf("Could not read pending message.\n");
1401 static int tokenize_cmd(char *cmd, char *argv[])
1414 if (argc == max_args)
1417 char *pos2 = os_strrchr(pos, '"');
1421 while (*pos != '\0' && *pos != ' ')
1431 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1433 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1434 printf("Connection to hostapd lost - trying to reconnect\n");
1435 hostapd_cli_close_connection();
1438 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1440 printf("Connection to hostapd re-established\n");
1441 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1442 hostapd_cli_attached = 1;
1444 printf("Warning: Failed to attach to "
1450 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1451 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1455 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1461 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1463 char *argv[max_args];
1465 argc = tokenize_cmd(cmd, argv);
1467 wpa_request(ctrl_conn, argc, argv);
1471 static void hostapd_cli_edit_eof_cb(void *ctx)
1477 static char ** list_cmd_list(void)
1482 count = ARRAY_SIZE(hostapd_cli_commands);
1483 res = os_calloc(count + 1, sizeof(char *));
1487 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1488 res[i] = os_strdup(hostapd_cli_commands[i].cmd);
1497 static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
1502 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1503 if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
1505 if (hostapd_cli_commands[i].completion)
1506 return hostapd_cli_commands[i].completion(str, pos);
1507 if (!hostapd_cli_commands[i].usage)
1510 printf("\r%s\n", hostapd_cli_commands[i].usage);
1519 static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
1526 end = os_strchr(str, ' ');
1527 if (end == NULL || str + pos < end)
1528 return list_cmd_list();
1530 cmd = os_malloc(pos + 1);
1533 os_memcpy(cmd, str, pos);
1534 cmd[end - str] = '\0';
1535 res = hostapd_cli_cmd_completion(cmd, str, pos);
1541 static void hostapd_cli_interactive(void)
1543 printf("\nInteractive mode\n\n");
1545 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1546 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1547 hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
1548 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1552 edit_deinit(NULL, NULL);
1553 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1557 static void hostapd_cli_cleanup(void)
1559 hostapd_cli_close_connection();
1561 os_daemonize_terminate(pid_file);
1563 os_program_deinit();
1567 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1575 fd = wpa_ctrl_get_fd(ctrl);
1577 while (!hostapd_cli_quit) {
1580 tv.tv_sec = ping_interval;
1582 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1583 if (res < 0 && errno != EINTR) {
1588 if (FD_ISSET(fd, &rfds))
1589 hostapd_cli_recv_pending(ctrl, 0, 1);
1591 len = sizeof(buf) - 1;
1592 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1593 hostapd_cli_action_process) < 0 ||
1594 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1595 printf("hostapd did not reply to PING "
1596 "command - exiting\n");
1604 int main(int argc, char *argv[])
1606 int warning_displayed = 0;
1610 if (os_program_init())
1614 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1619 action_file = optarg;
1625 ping_interval = atoi(optarg);
1631 printf("%s\n", hostapd_cli_version);
1634 os_free(ctrl_ifname);
1635 ctrl_ifname = os_strdup(optarg);
1638 ctrl_iface_dir = optarg;
1644 client_socket_dir = optarg;
1652 interactive = (argc == optind) && (action_file == NULL);
1655 printf("%s\n\n%s\n\n", hostapd_cli_version,
1656 hostapd_cli_license);
1663 if (ctrl_ifname == NULL) {
1664 struct dirent *dent;
1665 DIR *dir = opendir(ctrl_iface_dir);
1667 while ((dent = readdir(dir))) {
1668 if (os_strcmp(dent->d_name, ".") == 0
1670 os_strcmp(dent->d_name, "..") == 0)
1672 printf("Selected interface '%s'\n",
1674 ctrl_ifname = os_strdup(dent->d_name);
1680 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1682 if (warning_displayed)
1683 printf("Connection established.\n");
1688 perror("Failed to connect to hostapd - "
1693 if (!warning_displayed) {
1694 printf("Could not connect to hostapd - re-trying\n");
1695 warning_displayed = 1;
1701 if (interactive || action_file) {
1702 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1703 hostapd_cli_attached = 1;
1705 printf("Warning: Failed to attach to hostapd.\n");
1711 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1715 hostapd_cli_interactive();
1716 else if (action_file)
1717 hostapd_cli_action(ctrl_conn);
1719 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1721 os_free(ctrl_ifname);
1723 hostapd_cli_cleanup();
1727 #else /* CONFIG_NO_CTRL_IFACE */
1729 int main(int argc, char *argv[])
1734 #endif /* CONFIG_NO_CTRL_IFACE */