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"
18 #include "common/cli.h"
20 #ifndef CONFIG_NO_CTRL_IFACE
22 static const char *const hostapd_cli_version =
23 "hostapd_cli v" VERSION_STR "\n"
24 "Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
27 static const char *const hostapd_cli_license =
28 "This software may be distributed under the terms of the BSD license.\n"
29 "See README for more details.\n";
31 static const char *const hostapd_cli_full_license =
32 "This software may be distributed under the terms of the BSD license.\n"
34 "Redistribution and use in source and binary forms, with or without\n"
35 "modification, are permitted provided that the following conditions are\n"
38 "1. Redistributions of source code must retain the above copyright\n"
39 " notice, this list of conditions and the following disclaimer.\n"
41 "2. Redistributions in binary form must reproduce the above copyright\n"
42 " notice, this list of conditions and the following disclaimer in the\n"
43 " documentation and/or other materials provided with the distribution.\n"
45 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
46 " names of its contributors may be used to endorse or promote products\n"
47 " derived from this software without specific prior written permission.\n"
49 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
50 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
51 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
52 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
53 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
54 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
55 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
56 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
57 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
58 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
59 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
62 static struct wpa_ctrl *ctrl_conn;
63 static int hostapd_cli_quit = 0;
64 static int hostapd_cli_attached = 0;
66 #ifndef CONFIG_CTRL_IFACE_DIR
67 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
68 #endif /* CONFIG_CTRL_IFACE_DIR */
69 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
70 static const char *client_socket_dir = NULL;
72 static char *ctrl_ifname = NULL;
73 static const char *pid_file = NULL;
74 static const char *action_file = NULL;
75 static int ping_interval = 5;
76 static int interactive = 0;
77 static int event_handler_registered = 0;
79 static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */
81 static void print_help(FILE *stream, const char *cmd);
82 static char ** list_cmd_list(void);
83 static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx);
86 static void usage(void)
88 fprintf(stderr, "%s\n", hostapd_cli_version);
91 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
93 " [-P<pid file>] [-G<ping interval>] [command..]\n"
96 " -h help (show this usage text)\n"
97 " -v shown version information\n"
98 " -p<path> path to find control sockets (default: "
100 " -s<dir_path> dir path to open client sockets (default: "
101 CONFIG_CTRL_IFACE_DIR ")\n"
102 " -a<file> run in daemon mode executing the action file "
105 " -B run a daemon in the background\n"
106 " -i<ifname> Interface to listen on (default: first "
107 "interface found in the\n"
108 " socket path)\n\n");
109 print_help(stderr, NULL);
113 static int get_cmd_arg_num(const char *str, int pos)
117 for (i = 0; i <= pos; i++) {
120 while (i <= pos && str[i] != ' ')
131 static int str_starts(const char *src, const char *match)
133 return os_strncmp(src, match, os_strlen(match)) == 0;
137 static void register_event_handler(struct wpa_ctrl *ctrl)
142 event_handler_registered =
143 !eloop_register_read_sock(wpa_ctrl_get_fd(ctrl),
150 static void unregister_event_handler(struct wpa_ctrl *ctrl)
154 if (interactive && event_handler_registered) {
155 eloop_unregister_read_sock(wpa_ctrl_get_fd(ctrl));
156 event_handler_registered = 0;
161 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
163 #ifndef CONFIG_CTRL_IFACE_UDP
166 #endif /* !CONFIG_CTRL_IFACE_UDP */
171 #ifdef CONFIG_CTRL_IFACE_UDP
172 ctrl_conn = wpa_ctrl_open(ifname);
174 #else /* CONFIG_CTRL_IFACE_UDP */
175 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
176 cfile = malloc(flen);
179 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
181 if (client_socket_dir && client_socket_dir[0] &&
182 access(client_socket_dir, F_OK) < 0) {
183 perror(client_socket_dir);
188 ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
191 #endif /* CONFIG_CTRL_IFACE_UDP */
195 static void hostapd_cli_close_connection(void)
197 if (ctrl_conn == NULL)
200 unregister_event_handler(ctrl_conn);
201 if (hostapd_cli_attached) {
202 wpa_ctrl_detach(ctrl_conn);
203 hostapd_cli_attached = 0;
205 wpa_ctrl_close(ctrl_conn);
210 static void hostapd_cli_msg_cb(char *msg, size_t len)
216 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
222 if (ctrl_conn == NULL) {
223 printf("Not connected to hostapd - command dropped.\n");
226 len = sizeof(buf) - 1;
227 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
230 printf("'%s' command timed out.\n", cmd);
232 } else if (ret < 0) {
233 printf("'%s' command failed.\n", cmd);
244 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
246 return _wpa_ctrl_command(ctrl, cmd, 1);
250 static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
259 res = os_snprintf(pos, end - pos, "%s", cmd);
260 if (os_snprintf_error(end - pos, res))
264 for (i = 0; i < argc; i++) {
265 res = os_snprintf(pos, end - pos, " %s", argv[i]);
266 if (os_snprintf_error(end - pos, res))
271 buf[buflen - 1] = '\0';
275 printf("Too long command\n");
280 static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
281 int min_args, int argc, char *argv[])
285 if (argc < min_args) {
286 printf("Invalid %s command - at least %d argument%s required.\n",
287 cmd, min_args, min_args > 1 ? "s are" : " is");
290 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
292 return wpa_ctrl_command(ctrl, buf);
296 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
298 return wpa_ctrl_command(ctrl, "PING");
302 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
304 return wpa_ctrl_command(ctrl, "RELOG");
308 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
310 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
311 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
312 return wpa_ctrl_command(ctrl, "STATUS");
316 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
320 os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
321 return wpa_ctrl_command(ctrl, buf);
323 return wpa_ctrl_command(ctrl, "MIB");
327 static int hostapd_cli_exec(const char *program, const char *arg1,
334 len = os_strlen(arg1) + os_strlen(arg2) + 2;
335 arg = os_malloc(len);
338 os_snprintf(arg, len, "%s %s", arg1, arg2);
339 res = os_exec(program, arg, 1);
346 static void hostapd_cli_action_process(char *msg, size_t len)
352 pos = os_strchr(pos, '>');
359 hostapd_cli_exec(action_file, ctrl_ifname, pos);
363 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
367 printf("Invalid 'sta' command - at least one argument, STA "
368 "address, is required.\n");
372 snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
374 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
375 return wpa_ctrl_command(ctrl, buf);
379 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
384 printf("Invalid 'new_sta' command - exactly one argument, STA "
385 "address, is required.\n");
388 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
389 return wpa_ctrl_command(ctrl, buf);
393 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
398 printf("Invalid 'deauthenticate' command - exactly one "
399 "argument, STA address, is required.\n");
403 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
406 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
407 return wpa_ctrl_command(ctrl, buf);
411 static char ** hostapd_complete_deauthenticate(const char *str, int pos)
413 int arg = get_cmd_arg_num(str, pos);
418 res = cli_txt_list_array(&stations);
426 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
431 printf("Invalid 'disassociate' command - exactly one "
432 "argument, STA address, is required.\n");
436 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
439 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
440 return wpa_ctrl_command(ctrl, buf);
444 static char ** hostapd_complete_disassociate(const char *str, int pos)
446 int arg = get_cmd_arg_num(str, pos);
451 res = cli_txt_list_array(&stations);
459 #ifdef CONFIG_IEEE80211W
460 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
465 printf("Invalid 'sa_query' command - exactly one argument, "
466 "STA address, is required.\n");
469 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
470 return wpa_ctrl_command(ctrl, buf);
472 #endif /* CONFIG_IEEE80211W */
476 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
481 printf("Invalid 'wps_pin' command - at least two arguments, "
482 "UUID and PIN, are required.\n");
486 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
487 argv[0], argv[1], argv[2], argv[3]);
489 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
490 argv[0], argv[1], argv[2]);
492 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
493 return wpa_ctrl_command(ctrl, buf);
497 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
503 if (argc != 1 && argc != 2) {
504 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
505 "- PIN to be verified\n");
510 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
513 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
515 if (os_snprintf_error(sizeof(cmd), res)) {
516 printf("Too long WPS_CHECK_PIN command.\n");
519 return wpa_ctrl_command(ctrl, cmd);
523 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
526 return wpa_ctrl_command(ctrl, "WPS_PBC");
530 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
533 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
537 #ifdef CONFIG_WPS_NFC
538 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
546 printf("Invalid 'wps_nfc_tag_read' command - one argument "
551 buflen = 18 + os_strlen(argv[0]);
552 buf = os_malloc(buflen);
555 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
557 ret = wpa_ctrl_command(ctrl, buf);
564 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
565 int argc, char *argv[])
571 printf("Invalid 'wps_nfc_config_token' command - one argument "
576 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
578 if (os_snprintf_error(sizeof(cmd), res)) {
579 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
582 return wpa_ctrl_command(ctrl, cmd);
586 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
587 int argc, char *argv[])
593 printf("Invalid 'wps_nfc_token' command - one argument is "
598 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
599 if (os_snprintf_error(sizeof(cmd), res)) {
600 printf("Too long WPS_NFC_TOKEN command.\n");
603 return wpa_ctrl_command(ctrl, cmd);
607 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
608 int argc, char *argv[])
614 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
619 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
621 if (os_snprintf_error(sizeof(cmd), res)) {
622 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
625 return wpa_ctrl_command(ctrl, cmd);
628 #endif /* CONFIG_WPS_NFC */
631 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
636 printf("Invalid 'wps_ap_pin' command - at least one argument "
641 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
642 argv[0], argv[1], argv[2]);
644 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
647 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
648 return wpa_ctrl_command(ctrl, buf);
652 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
655 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
659 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
663 char ssid_hex[2 * SSID_MAX_LEN + 1];
664 char key_hex[2 * 64 + 1];
668 printf("Invalid 'wps_config' command - at least two arguments "
674 for (i = 0; i < SSID_MAX_LEN; i++) {
675 if (argv[0][i] == '\0')
677 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
682 for (i = 0; i < 64; i++) {
683 if (argv[3][i] == '\0')
685 os_snprintf(&key_hex[i * 2], 3, "%02x",
691 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
692 ssid_hex, argv[1], argv[2], key_hex);
694 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
695 ssid_hex, argv[1], argv[2]);
697 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
699 return wpa_ctrl_command(ctrl, buf);
701 #endif /* CONFIG_WPS */
704 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
711 printf("Invalid 'disassoc_imminent' command - two arguments "
712 "(STA addr and Disassociation Timer) are needed\n");
716 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
718 if (os_snprintf_error(sizeof(buf), res))
720 return wpa_ctrl_command(ctrl, buf);
724 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
731 printf("Invalid 'ess_disassoc' command - three arguments (STA "
732 "addr, disassoc timer, and URL) are needed\n");
736 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
737 argv[0], argv[1], argv[2]);
738 if (os_snprintf_error(sizeof(buf), res))
740 return wpa_ctrl_command(ctrl, buf);
744 static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
747 char buf[2000], *tmp;
751 printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
755 res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
756 if (os_snprintf_error(sizeof(buf), res))
760 for (i = 1; i < argc; i++) {
762 res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
763 if (os_snprintf_error(sizeof(buf) - total, res))
767 return wpa_ctrl_command(ctrl, buf);
771 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
774 return wpa_ctrl_command(ctrl, "GET_CONFIG");
778 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
779 char *addr, size_t addr_len)
781 char buf[4096], *pos;
785 if (ctrl_conn == NULL) {
786 printf("Not connected to hostapd - command dropped.\n");
789 len = sizeof(buf) - 1;
790 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
793 printf("'%s' command timed out.\n", cmd);
795 } else if (ret < 0) {
796 printf("'%s' command failed.\n", cmd);
801 if (memcmp(buf, "FAIL", 4) == 0)
806 while (*pos != '\0' && *pos != '\n')
809 os_strlcpy(addr, buf, addr_len);
814 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
817 char addr[32], cmd[64];
819 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
822 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
823 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
829 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
831 print_help(stdout, argc > 0 ? argv[0] : NULL);
836 static char ** hostapd_cli_complete_help(const char *str, int pos)
838 int arg = get_cmd_arg_num(str, pos);
843 res = list_cmd_list();
851 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
854 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
859 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
860 int argc, char *argv[])
866 printf("Invalid 'set_qos_map_set' command - "
867 "one argument (comma delimited QoS map set) "
872 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
873 if (os_snprintf_error(sizeof(buf), res))
875 return wpa_ctrl_command(ctrl, buf);
879 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
880 int argc, char *argv[])
886 printf("Invalid 'send_qos_map_conf' command - "
887 "one argument (STA addr) is needed\n");
891 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
892 if (os_snprintf_error(sizeof(buf), res))
894 return wpa_ctrl_command(ctrl, buf);
898 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
905 printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
906 "addr and URL) are needed\n");
910 res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
912 if (os_snprintf_error(sizeof(buf), res))
914 return wpa_ctrl_command(ctrl, buf);
918 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
925 printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
930 res = os_snprintf(buf, sizeof(buf),
931 "HS20_DEAUTH_REQ %s %s %s %s",
932 argv[0], argv[1], argv[2], argv[3]);
934 res = os_snprintf(buf, sizeof(buf),
935 "HS20_DEAUTH_REQ %s %s %s",
936 argv[0], argv[1], argv[2]);
937 if (os_snprintf_error(sizeof(buf), res))
939 return wpa_ctrl_command(ctrl, buf);
943 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
945 hostapd_cli_quit = 1;
952 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
956 printf("Invalid LEVEL command: needs one argument (debug "
960 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
961 return wpa_ctrl_command(ctrl, cmd);
965 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
970 dir = opendir(ctrl_iface_dir);
972 printf("Control interface directory '%s' could not be "
973 "openned.\n", ctrl_iface_dir);
977 printf("Available interfaces:\n");
978 while ((dent = readdir(dir))) {
979 if (strcmp(dent->d_name, ".") == 0 ||
980 strcmp(dent->d_name, "..") == 0)
982 printf("%s\n", dent->d_name);
988 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
992 hostapd_cli_list_interfaces(ctrl);
996 hostapd_cli_close_connection();
997 os_free(ctrl_ifname);
998 ctrl_ifname = os_strdup(argv[0]);
999 if (ctrl_ifname == NULL)
1002 if (hostapd_cli_open_connection(ctrl_ifname)) {
1003 printf("Connected to interface '%s.\n", ctrl_ifname);
1004 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1005 hostapd_cli_attached = 1;
1006 register_event_handler(ctrl_conn);
1008 printf("Warning: Failed to attach to "
1012 printf("Could not connect to interface '%s' - re-trying\n",
1019 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
1025 printf("Invalid SET command: needs two arguments (variable "
1026 "name and value)\n");
1030 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
1031 if (os_snprintf_error(sizeof(cmd), res)) {
1032 printf("Too long SET command.\n");
1035 return wpa_ctrl_command(ctrl, cmd);
1039 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
1045 printf("Invalid GET command: needs one argument (variable "
1050 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
1051 if (os_snprintf_error(sizeof(cmd), res)) {
1052 printf("Too long GET command.\n");
1055 return wpa_ctrl_command(ctrl, cmd);
1060 static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
1068 printf("FST command: parameters are required.\n");
1072 total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
1074 for (i = 0; i < argc; i++) {
1075 res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
1077 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1078 printf("Too long fst command.\n");
1083 return wpa_ctrl_command(ctrl, cmd);
1085 #endif /* CONFIG_FST */
1088 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
1089 int argc, char *argv[])
1098 printf("Invalid chan_switch command: needs at least two "
1099 "arguments (count and freq)\n"
1100 "usage: <cs_count> <freq> [sec_channel_offset=] "
1101 "[center_freq1=] [center_freq2=] [bandwidth=] "
1102 "[blocktx] [ht|vht]\n");
1106 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
1108 if (os_snprintf_error(sizeof(cmd), res)) {
1109 printf("Too long CHAN_SWITCH command.\n");
1114 for (i = 2; i < argc; i++) {
1116 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
1117 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1118 printf("Too long CHAN_SWITCH command.\n");
1123 return wpa_ctrl_command(ctrl, cmd);
1127 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
1130 return wpa_ctrl_command(ctrl, "ENABLE");
1134 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
1137 return wpa_ctrl_command(ctrl, "RELOAD");
1141 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
1144 return wpa_ctrl_command(ctrl, "DISABLE");
1148 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
1153 if (argc < 2 || argc > 3) {
1154 printf("Invalid vendor command\n"
1155 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
1159 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
1160 argc == 3 ? argv[2] : "");
1161 if (os_snprintf_error(sizeof(cmd), res)) {
1162 printf("Too long VENDOR command.\n");
1165 return wpa_ctrl_command(ctrl, cmd);
1169 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1172 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1176 static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
1182 res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
1183 argc >= 1 ? " " : "",
1184 argc >= 1 ? argv[0] : "",
1185 argc == 2 ? " " : "",
1186 argc == 2 ? argv[1] : "");
1187 if (os_snprintf_error(sizeof(cmd), res)) {
1188 printf("Too long option\n");
1191 return wpa_ctrl_command(ctrl, cmd);
1195 static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
1199 return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
1203 static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1205 return wpa_ctrl_command(ctrl, "PMKSA");
1209 static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
1212 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
1216 static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
1222 if (argc < 3 || argc > 5) {
1223 printf("Invalid set_neighbor command: needs 3-5 arguments\n");
1227 res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
1228 argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
1229 argc == 5 ? argv[4] : "");
1230 if (os_snprintf_error(sizeof(cmd), res)) {
1231 printf("Too long SET_NEIGHBOR command.\n");
1234 return wpa_ctrl_command(ctrl, cmd);
1238 static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
1245 printf("Invalid remove_neighbor command: needs 2 arguments\n");
1249 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
1251 if (os_snprintf_error(sizeof(cmd), res)) {
1252 printf("Too long REMOVE_NEIGHBOR command.\n");
1255 return wpa_ctrl_command(ctrl, cmd);
1259 static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
1266 printf("Invalid req_lci command - requires destination address\n");
1270 res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
1271 if (os_snprintf_error(sizeof(cmd), res)) {
1272 printf("Too long REQ_LCI command.\n");
1275 return wpa_ctrl_command(ctrl, cmd);
1279 static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
1283 printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
1287 return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
1291 static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
1294 return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
1298 struct hostapd_cli_cmd {
1300 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1301 char ** (*completion)(const char *str, int pos);
1305 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1306 { "ping", hostapd_cli_cmd_ping, NULL,
1307 "= pings hostapd" },
1308 { "mib", hostapd_cli_cmd_mib, NULL,
1309 "= get MIB variables (dot1x, dot11, radius)" },
1310 { "relog", hostapd_cli_cmd_relog, NULL, NULL },
1311 { "status", hostapd_cli_cmd_status, NULL, NULL },
1312 { "sta", hostapd_cli_cmd_sta, NULL,
1313 "<addr> = get MIB variables for one station" },
1314 { "all_sta", hostapd_cli_cmd_all_sta, NULL,
1315 "= get MIB variables for all stations" },
1316 { "new_sta", hostapd_cli_cmd_new_sta, NULL,
1317 "<addr> = add a new station" },
1318 { "deauthenticate", hostapd_cli_cmd_deauthenticate,
1319 hostapd_complete_deauthenticate,
1320 "<addr> = deauthenticate a station" },
1321 { "disassociate", hostapd_cli_cmd_disassociate,
1322 hostapd_complete_disassociate,
1323 "<addr> = disassociate a station" },
1324 #ifdef CONFIG_IEEE80211W
1325 { "sa_query", hostapd_cli_cmd_sa_query, NULL,
1326 "<addr> = send SA Query to a station" },
1327 #endif /* CONFIG_IEEE80211W */
1329 { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
1330 "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
1331 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
1332 "<PIN> = verify PIN checksum" },
1333 { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
1334 "= indicate button pushed to initiate PBC" },
1335 { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
1336 "= cancel the pending WPS operation" },
1337 #ifdef CONFIG_WPS_NFC
1338 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
1339 "<hexdump> = report read NFC tag with WPS data" },
1340 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
1341 "<WPS/NDEF> = build NFC configuration token" },
1342 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
1343 "<WPS/NDEF/enable/disable> = manager NFC password token" },
1344 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
1346 #endif /* CONFIG_WPS_NFC */
1347 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
1348 "<cmd> [params..] = enable/disable AP PIN" },
1349 { "wps_config", hostapd_cli_cmd_wps_config, NULL,
1350 "<SSID> <auth> <encr> <key> = configure AP" },
1351 { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
1352 "= show current WPS status" },
1353 #endif /* CONFIG_WPS */
1354 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
1355 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
1356 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
1357 { "get_config", hostapd_cli_cmd_get_config, NULL,
1358 "= show current configuration" },
1359 { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
1360 "= show this usage help" },
1361 { "interface", hostapd_cli_cmd_interface, NULL,
1362 "[ifname] = show interfaces/select interface" },
1364 { "fst", hostapd_cli_cmd_fst, NULL, NULL },
1365 #endif /* CONFIG_FST */
1366 { "raw", hostapd_cli_cmd_raw, NULL, NULL },
1367 { "level", hostapd_cli_cmd_level, NULL,
1368 "<debug level> = change debug level" },
1369 { "license", hostapd_cli_cmd_license, NULL,
1370 "= show full hostapd_cli license" },
1371 { "quit", hostapd_cli_cmd_quit, NULL,
1372 "= exit hostapd_cli" },
1373 { "set", hostapd_cli_cmd_set, NULL, NULL },
1374 { "get", hostapd_cli_cmd_get, NULL, NULL },
1375 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
1376 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
1377 { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
1378 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
1379 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
1380 { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
1381 { "enable", hostapd_cli_cmd_enable, NULL, NULL },
1382 { "reload", hostapd_cli_cmd_reload, NULL, NULL },
1383 { "disable", hostapd_cli_cmd_disable, NULL, NULL },
1384 { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
1385 { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
1386 { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
1387 { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
1388 { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
1389 { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
1390 { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
1391 { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
1392 { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
1393 { NULL, NULL, NULL, NULL }
1398 * Prints command usage, lines are padded with the specified string.
1400 static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
1406 if (cmd->usage == NULL)
1408 fprintf(stream, "%s%s ", pad, cmd->cmd);
1409 for (n = 0; (c = cmd->usage[n]); n++) {
1410 fprintf(stream, "%c", c);
1412 fprintf(stream, "%s", pad);
1414 fprintf(stream, "\n");
1418 static void print_help(FILE *stream, const char *cmd)
1422 fprintf(stream, "commands:\n");
1423 for (n = 0; hostapd_cli_commands[n].cmd; n++) {
1424 if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
1425 print_cmd_help(stream, &hostapd_cli_commands[n], " ");
1430 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1432 const struct hostapd_cli_cmd *cmd, *match = NULL;
1436 cmd = hostapd_cli_commands;
1438 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1440 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1441 /* we have an exact match */
1451 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1452 cmd = hostapd_cli_commands;
1454 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1456 printf(" %s", cmd->cmd);
1461 } else if (count == 0) {
1462 printf("Unknown command '%s'\n", argv[0]);
1464 match->handler(ctrl, argc - 1, &argv[1]);
1469 static void cli_event(const char *str)
1471 const char *start, *s;
1473 start = os_strchr(str, '>');
1479 if (str_starts(start, AP_STA_CONNECTED)) {
1480 s = os_strchr(start, ' ');
1483 cli_txt_list_add(&stations, s + 1);
1487 if (str_starts(start, AP_STA_DISCONNECTED)) {
1488 s = os_strchr(start, ' ');
1491 cli_txt_list_del_addr(&stations, s + 1);
1497 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1501 if (ctrl_conn == NULL)
1503 while (wpa_ctrl_pending(ctrl)) {
1505 size_t len = sizeof(buf) - 1;
1506 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1509 hostapd_cli_action_process(buf, len);
1512 if (in_read && first)
1515 printf("%s\n", buf);
1518 printf("Could not read pending message.\n");
1525 static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx)
1527 hostapd_cli_recv_pending(ctrl_conn, 0, 0);
1533 static int tokenize_cmd(char *cmd, char *argv[])
1546 if (argc == max_args)
1549 char *pos2 = os_strrchr(pos, '"');
1553 while (*pos != '\0' && *pos != ' ')
1563 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1565 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1566 printf("Connection to hostapd lost - trying to reconnect\n");
1567 hostapd_cli_close_connection();
1570 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1572 printf("Connection to hostapd re-established\n");
1573 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1574 hostapd_cli_attached = 1;
1575 register_event_handler(ctrl_conn);
1577 printf("Warning: Failed to attach to "
1583 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1584 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1588 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1594 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1596 char *argv[max_args];
1598 argc = tokenize_cmd(cmd, argv);
1600 wpa_request(ctrl_conn, argc, argv);
1604 static void hostapd_cli_edit_eof_cb(void *ctx)
1610 static char ** list_cmd_list(void)
1615 count = ARRAY_SIZE(hostapd_cli_commands);
1616 res = os_calloc(count + 1, sizeof(char *));
1620 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1621 res[i] = os_strdup(hostapd_cli_commands[i].cmd);
1630 static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
1635 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1636 if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
1638 if (hostapd_cli_commands[i].completion)
1639 return hostapd_cli_commands[i].completion(str, pos);
1640 if (!hostapd_cli_commands[i].usage)
1643 printf("\r%s\n", hostapd_cli_commands[i].usage);
1652 static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
1659 end = os_strchr(str, ' ');
1660 if (end == NULL || str + pos < end)
1661 return list_cmd_list();
1663 cmd = os_malloc(pos + 1);
1666 os_memcpy(cmd, str, pos);
1667 cmd[end - str] = '\0';
1668 res = hostapd_cli_cmd_completion(cmd, str, pos);
1674 static void hostapd_cli_interactive(void)
1676 printf("\nInteractive mode\n\n");
1678 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1679 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1680 hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
1681 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1685 cli_txt_list_flush(&stations);
1686 edit_deinit(NULL, NULL);
1687 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1691 static void hostapd_cli_cleanup(void)
1693 hostapd_cli_close_connection();
1695 os_daemonize_terminate(pid_file);
1697 os_program_deinit();
1701 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1709 fd = wpa_ctrl_get_fd(ctrl);
1711 while (!hostapd_cli_quit) {
1714 tv.tv_sec = ping_interval;
1716 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1717 if (res < 0 && errno != EINTR) {
1722 if (FD_ISSET(fd, &rfds))
1723 hostapd_cli_recv_pending(ctrl, 0, 1);
1725 len = sizeof(buf) - 1;
1726 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1727 hostapd_cli_action_process) < 0 ||
1728 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1729 printf("hostapd did not reply to PING "
1730 "command - exiting\n");
1738 int main(int argc, char *argv[])
1740 int warning_displayed = 0;
1744 if (os_program_init())
1748 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1753 action_file = optarg;
1759 ping_interval = atoi(optarg);
1765 printf("%s\n", hostapd_cli_version);
1768 os_free(ctrl_ifname);
1769 ctrl_ifname = os_strdup(optarg);
1772 ctrl_iface_dir = optarg;
1778 client_socket_dir = optarg;
1786 interactive = (argc == optind) && (action_file == NULL);
1789 printf("%s\n\n%s\n\n", hostapd_cli_version,
1790 hostapd_cli_license);
1797 if (ctrl_ifname == NULL) {
1798 struct dirent *dent;
1799 DIR *dir = opendir(ctrl_iface_dir);
1801 while ((dent = readdir(dir))) {
1802 if (os_strcmp(dent->d_name, ".") == 0
1804 os_strcmp(dent->d_name, "..") == 0)
1806 printf("Selected interface '%s'\n",
1808 ctrl_ifname = os_strdup(dent->d_name);
1814 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1816 if (warning_displayed)
1817 printf("Connection established.\n");
1822 perror("Failed to connect to hostapd - "
1827 if (!warning_displayed) {
1828 printf("Could not connect to hostapd - re-trying\n");
1829 warning_displayed = 1;
1835 if (interactive || action_file) {
1836 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1837 hostapd_cli_attached = 1;
1838 register_event_handler(ctrl_conn);
1840 printf("Warning: Failed to attach to hostapd.\n");
1846 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1850 hostapd_cli_interactive();
1851 else if (action_file)
1852 hostapd_cli_action(ctrl_conn);
1854 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1856 unregister_event_handler(ctrl_conn);
1857 os_free(ctrl_ifname);
1859 hostapd_cli_cleanup();
1863 #else /* CONFIG_NO_CTRL_IFACE */
1865 int main(int argc, char *argv[])
1870 #endif /* CONFIG_NO_CTRL_IFACE */