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_get_interfaces(struct wpa_ctrl *ctrl,
966 struct dl_list *interfaces)
971 if (!ctrl || !interfaces)
973 dir = opendir(ctrl_iface_dir);
977 while ((dent = readdir(dir))) {
978 if (strcmp(dent->d_name, ".") == 0 ||
979 strcmp(dent->d_name, "..") == 0)
981 cli_txt_list_add(interfaces, dent->d_name);
987 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
992 dir = opendir(ctrl_iface_dir);
994 printf("Control interface directory '%s' could not be "
995 "openned.\n", ctrl_iface_dir);
999 printf("Available interfaces:\n");
1000 while ((dent = readdir(dir))) {
1001 if (strcmp(dent->d_name, ".") == 0 ||
1002 strcmp(dent->d_name, "..") == 0)
1004 printf("%s\n", dent->d_name);
1010 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
1014 hostapd_cli_list_interfaces(ctrl);
1018 hostapd_cli_close_connection();
1019 os_free(ctrl_ifname);
1020 ctrl_ifname = os_strdup(argv[0]);
1021 if (ctrl_ifname == NULL)
1024 if (hostapd_cli_open_connection(ctrl_ifname)) {
1025 printf("Connected to interface '%s.\n", ctrl_ifname);
1026 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1027 hostapd_cli_attached = 1;
1028 register_event_handler(ctrl_conn);
1030 printf("Warning: Failed to attach to "
1034 printf("Could not connect to interface '%s' - re-trying\n",
1041 static char ** hostapd_complete_interface(const char *str, int pos)
1043 int arg = get_cmd_arg_num(str, pos);
1045 DEFINE_DL_LIST(interfaces);
1049 hostapd_cli_get_interfaces(ctrl_conn, &interfaces);
1050 res = cli_txt_list_array(&interfaces);
1051 cli_txt_list_flush(&interfaces);
1059 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
1065 printf("Invalid SET command: needs two arguments (variable "
1066 "name and value)\n");
1070 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
1071 if (os_snprintf_error(sizeof(cmd), res)) {
1072 printf("Too long SET command.\n");
1075 return wpa_ctrl_command(ctrl, cmd);
1079 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
1085 printf("Invalid GET command: needs one argument (variable "
1090 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
1091 if (os_snprintf_error(sizeof(cmd), res)) {
1092 printf("Too long GET command.\n");
1095 return wpa_ctrl_command(ctrl, cmd);
1100 static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
1108 printf("FST command: parameters are required.\n");
1112 total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
1114 for (i = 0; i < argc; i++) {
1115 res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
1117 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1118 printf("Too long fst command.\n");
1123 return wpa_ctrl_command(ctrl, cmd);
1125 #endif /* CONFIG_FST */
1128 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
1129 int argc, char *argv[])
1138 printf("Invalid chan_switch command: needs at least two "
1139 "arguments (count and freq)\n"
1140 "usage: <cs_count> <freq> [sec_channel_offset=] "
1141 "[center_freq1=] [center_freq2=] [bandwidth=] "
1142 "[blocktx] [ht|vht]\n");
1146 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
1148 if (os_snprintf_error(sizeof(cmd), res)) {
1149 printf("Too long CHAN_SWITCH command.\n");
1154 for (i = 2; i < argc; i++) {
1156 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
1157 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1158 printf("Too long CHAN_SWITCH command.\n");
1163 return wpa_ctrl_command(ctrl, cmd);
1167 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
1170 return wpa_ctrl_command(ctrl, "ENABLE");
1174 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
1177 return wpa_ctrl_command(ctrl, "RELOAD");
1181 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
1184 return wpa_ctrl_command(ctrl, "DISABLE");
1188 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
1193 if (argc < 2 || argc > 3) {
1194 printf("Invalid vendor command\n"
1195 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
1199 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
1200 argc == 3 ? argv[2] : "");
1201 if (os_snprintf_error(sizeof(cmd), res)) {
1202 printf("Too long VENDOR command.\n");
1205 return wpa_ctrl_command(ctrl, cmd);
1209 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1212 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1216 static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
1222 res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
1223 argc >= 1 ? " " : "",
1224 argc >= 1 ? argv[0] : "",
1225 argc == 2 ? " " : "",
1226 argc == 2 ? argv[1] : "");
1227 if (os_snprintf_error(sizeof(cmd), res)) {
1228 printf("Too long option\n");
1231 return wpa_ctrl_command(ctrl, cmd);
1235 static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
1239 return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
1243 static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1245 return wpa_ctrl_command(ctrl, "PMKSA");
1249 static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
1252 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
1256 static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
1262 if (argc < 3 || argc > 5) {
1263 printf("Invalid set_neighbor command: needs 3-5 arguments\n");
1267 res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
1268 argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
1269 argc == 5 ? argv[4] : "");
1270 if (os_snprintf_error(sizeof(cmd), res)) {
1271 printf("Too long SET_NEIGHBOR command.\n");
1274 return wpa_ctrl_command(ctrl, cmd);
1278 static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
1285 printf("Invalid remove_neighbor command: needs 2 arguments\n");
1289 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
1291 if (os_snprintf_error(sizeof(cmd), res)) {
1292 printf("Too long REMOVE_NEIGHBOR command.\n");
1295 return wpa_ctrl_command(ctrl, cmd);
1299 static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
1306 printf("Invalid req_lci command - requires destination address\n");
1310 res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
1311 if (os_snprintf_error(sizeof(cmd), res)) {
1312 printf("Too long REQ_LCI command.\n");
1315 return wpa_ctrl_command(ctrl, cmd);
1319 static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
1323 printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
1327 return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
1331 static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
1334 return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
1338 struct hostapd_cli_cmd {
1340 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1341 char ** (*completion)(const char *str, int pos);
1345 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1346 { "ping", hostapd_cli_cmd_ping, NULL,
1347 "= pings hostapd" },
1348 { "mib", hostapd_cli_cmd_mib, NULL,
1349 "= get MIB variables (dot1x, dot11, radius)" },
1350 { "relog", hostapd_cli_cmd_relog, NULL, NULL },
1351 { "status", hostapd_cli_cmd_status, NULL, NULL },
1352 { "sta", hostapd_cli_cmd_sta, NULL,
1353 "<addr> = get MIB variables for one station" },
1354 { "all_sta", hostapd_cli_cmd_all_sta, NULL,
1355 "= get MIB variables for all stations" },
1356 { "new_sta", hostapd_cli_cmd_new_sta, NULL,
1357 "<addr> = add a new station" },
1358 { "deauthenticate", hostapd_cli_cmd_deauthenticate,
1359 hostapd_complete_deauthenticate,
1360 "<addr> = deauthenticate a station" },
1361 { "disassociate", hostapd_cli_cmd_disassociate,
1362 hostapd_complete_disassociate,
1363 "<addr> = disassociate a station" },
1364 #ifdef CONFIG_IEEE80211W
1365 { "sa_query", hostapd_cli_cmd_sa_query, NULL,
1366 "<addr> = send SA Query to a station" },
1367 #endif /* CONFIG_IEEE80211W */
1369 { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
1370 "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
1371 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
1372 "<PIN> = verify PIN checksum" },
1373 { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
1374 "= indicate button pushed to initiate PBC" },
1375 { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
1376 "= cancel the pending WPS operation" },
1377 #ifdef CONFIG_WPS_NFC
1378 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
1379 "<hexdump> = report read NFC tag with WPS data" },
1380 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
1381 "<WPS/NDEF> = build NFC configuration token" },
1382 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
1383 "<WPS/NDEF/enable/disable> = manager NFC password token" },
1384 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
1386 #endif /* CONFIG_WPS_NFC */
1387 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
1388 "<cmd> [params..] = enable/disable AP PIN" },
1389 { "wps_config", hostapd_cli_cmd_wps_config, NULL,
1390 "<SSID> <auth> <encr> <key> = configure AP" },
1391 { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
1392 "= show current WPS status" },
1393 #endif /* CONFIG_WPS */
1394 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
1395 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
1396 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
1397 { "get_config", hostapd_cli_cmd_get_config, NULL,
1398 "= show current configuration" },
1399 { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
1400 "= show this usage help" },
1401 { "interface", hostapd_cli_cmd_interface, hostapd_complete_interface,
1402 "[ifname] = show interfaces/select interface" },
1404 { "fst", hostapd_cli_cmd_fst, NULL, NULL },
1405 #endif /* CONFIG_FST */
1406 { "raw", hostapd_cli_cmd_raw, NULL, NULL },
1407 { "level", hostapd_cli_cmd_level, NULL,
1408 "<debug level> = change debug level" },
1409 { "license", hostapd_cli_cmd_license, NULL,
1410 "= show full hostapd_cli license" },
1411 { "quit", hostapd_cli_cmd_quit, NULL,
1412 "= exit hostapd_cli" },
1413 { "set", hostapd_cli_cmd_set, NULL, NULL },
1414 { "get", hostapd_cli_cmd_get, NULL, NULL },
1415 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
1416 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
1417 { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
1418 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
1419 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
1420 { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
1421 { "enable", hostapd_cli_cmd_enable, NULL, NULL },
1422 { "reload", hostapd_cli_cmd_reload, NULL, NULL },
1423 { "disable", hostapd_cli_cmd_disable, NULL, NULL },
1424 { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
1425 { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
1426 { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
1427 { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
1428 { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
1429 { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
1430 { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
1431 { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
1432 { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
1433 { NULL, NULL, NULL, NULL }
1438 * Prints command usage, lines are padded with the specified string.
1440 static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
1446 if (cmd->usage == NULL)
1448 fprintf(stream, "%s%s ", pad, cmd->cmd);
1449 for (n = 0; (c = cmd->usage[n]); n++) {
1450 fprintf(stream, "%c", c);
1452 fprintf(stream, "%s", pad);
1454 fprintf(stream, "\n");
1458 static void print_help(FILE *stream, const char *cmd)
1462 fprintf(stream, "commands:\n");
1463 for (n = 0; hostapd_cli_commands[n].cmd; n++) {
1464 if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
1465 print_cmd_help(stream, &hostapd_cli_commands[n], " ");
1470 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1472 const struct hostapd_cli_cmd *cmd, *match = NULL;
1476 cmd = hostapd_cli_commands;
1478 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1480 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1481 /* we have an exact match */
1491 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1492 cmd = hostapd_cli_commands;
1494 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1496 printf(" %s", cmd->cmd);
1501 } else if (count == 0) {
1502 printf("Unknown command '%s'\n", argv[0]);
1504 match->handler(ctrl, argc - 1, &argv[1]);
1509 static void cli_event(const char *str)
1511 const char *start, *s;
1513 start = os_strchr(str, '>');
1519 if (str_starts(start, AP_STA_CONNECTED)) {
1520 s = os_strchr(start, ' ');
1523 cli_txt_list_add(&stations, s + 1);
1527 if (str_starts(start, AP_STA_DISCONNECTED)) {
1528 s = os_strchr(start, ' ');
1531 cli_txt_list_del_addr(&stations, s + 1);
1537 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1541 if (ctrl_conn == NULL)
1543 while (wpa_ctrl_pending(ctrl)) {
1545 size_t len = sizeof(buf) - 1;
1546 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1549 hostapd_cli_action_process(buf, len);
1552 if (in_read && first)
1555 printf("%s\n", buf);
1558 printf("Could not read pending message.\n");
1565 static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx)
1567 hostapd_cli_recv_pending(ctrl_conn, 0, 0);
1573 static int tokenize_cmd(char *cmd, char *argv[])
1586 if (argc == max_args)
1589 char *pos2 = os_strrchr(pos, '"');
1593 while (*pos != '\0' && *pos != ' ')
1603 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1605 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1606 printf("Connection to hostapd lost - trying to reconnect\n");
1607 hostapd_cli_close_connection();
1610 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1612 printf("Connection to hostapd re-established\n");
1613 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1614 hostapd_cli_attached = 1;
1615 register_event_handler(ctrl_conn);
1617 printf("Warning: Failed to attach to "
1623 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1624 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1628 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1634 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1636 char *argv[max_args];
1638 argc = tokenize_cmd(cmd, argv);
1640 wpa_request(ctrl_conn, argc, argv);
1644 static void hostapd_cli_edit_eof_cb(void *ctx)
1650 static char ** list_cmd_list(void)
1655 count = ARRAY_SIZE(hostapd_cli_commands);
1656 res = os_calloc(count + 1, sizeof(char *));
1660 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1661 res[i] = os_strdup(hostapd_cli_commands[i].cmd);
1670 static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
1675 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1676 if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
1678 if (hostapd_cli_commands[i].completion)
1679 return hostapd_cli_commands[i].completion(str, pos);
1680 if (!hostapd_cli_commands[i].usage)
1683 printf("\r%s\n", hostapd_cli_commands[i].usage);
1692 static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
1699 end = os_strchr(str, ' ');
1700 if (end == NULL || str + pos < end)
1701 return list_cmd_list();
1703 cmd = os_malloc(pos + 1);
1706 os_memcpy(cmd, str, pos);
1707 cmd[end - str] = '\0';
1708 res = hostapd_cli_cmd_completion(cmd, str, pos);
1714 static void hostapd_cli_interactive(void)
1716 printf("\nInteractive mode\n\n");
1718 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1719 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1720 hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
1721 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1725 cli_txt_list_flush(&stations);
1726 edit_deinit(NULL, NULL);
1727 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1731 static void hostapd_cli_cleanup(void)
1733 hostapd_cli_close_connection();
1735 os_daemonize_terminate(pid_file);
1737 os_program_deinit();
1741 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1749 fd = wpa_ctrl_get_fd(ctrl);
1751 while (!hostapd_cli_quit) {
1754 tv.tv_sec = ping_interval;
1756 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1757 if (res < 0 && errno != EINTR) {
1762 if (FD_ISSET(fd, &rfds))
1763 hostapd_cli_recv_pending(ctrl, 0, 1);
1765 len = sizeof(buf) - 1;
1766 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1767 hostapd_cli_action_process) < 0 ||
1768 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1769 printf("hostapd did not reply to PING "
1770 "command - exiting\n");
1778 int main(int argc, char *argv[])
1780 int warning_displayed = 0;
1784 if (os_program_init())
1788 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1793 action_file = optarg;
1799 ping_interval = atoi(optarg);
1805 printf("%s\n", hostapd_cli_version);
1808 os_free(ctrl_ifname);
1809 ctrl_ifname = os_strdup(optarg);
1812 ctrl_iface_dir = optarg;
1818 client_socket_dir = optarg;
1826 interactive = (argc == optind) && (action_file == NULL);
1829 printf("%s\n\n%s\n\n", hostapd_cli_version,
1830 hostapd_cli_license);
1837 if (ctrl_ifname == NULL) {
1838 struct dirent *dent;
1839 DIR *dir = opendir(ctrl_iface_dir);
1841 while ((dent = readdir(dir))) {
1842 if (os_strcmp(dent->d_name, ".") == 0
1844 os_strcmp(dent->d_name, "..") == 0)
1846 printf("Selected interface '%s'\n",
1848 ctrl_ifname = os_strdup(dent->d_name);
1854 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1856 if (warning_displayed)
1857 printf("Connection established.\n");
1862 perror("Failed to connect to hostapd - "
1867 if (!warning_displayed) {
1868 printf("Could not connect to hostapd - re-trying\n");
1869 warning_displayed = 1;
1875 if (interactive || action_file) {
1876 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1877 hostapd_cli_attached = 1;
1878 register_event_handler(ctrl_conn);
1880 printf("Warning: Failed to attach to hostapd.\n");
1886 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1890 hostapd_cli_interactive();
1891 else if (action_file)
1892 hostapd_cli_action(ctrl_conn);
1894 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1896 unregister_event_handler(ctrl_conn);
1897 os_free(ctrl_ifname);
1899 hostapd_cli_cleanup();
1903 #else /* CONFIG_NO_CTRL_IFACE */
1905 int main(int argc, char *argv[])
1910 #endif /* CONFIG_NO_CTRL_IFACE */