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);
78 static char ** list_cmd_list(void);
81 static void usage(void)
83 fprintf(stderr, "%s\n", hostapd_cli_version);
86 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
88 " [-P<pid file>] [-G<ping interval>] [command..]\n"
91 " -h help (show this usage text)\n"
92 " -v shown version information\n"
93 " -p<path> path to find control sockets (default: "
95 " -s<dir_path> dir path to open client sockets (default: "
96 CONFIG_CTRL_IFACE_DIR ")\n"
97 " -a<file> run in daemon mode executing the action file "
100 " -B run a daemon in the background\n"
101 " -i<ifname> Interface to listen on (default: first "
102 "interface found in the\n"
103 " socket path)\n\n");
104 print_help(stderr, NULL);
108 static int get_cmd_arg_num(const char *str, int pos)
112 for (i = 0; i <= pos; i++) {
115 while (i <= pos && str[i] != ' ')
126 static int str_starts(const char *src, const char *match)
128 return os_strncmp(src, match, os_strlen(match)) == 0;
132 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
134 #ifndef CONFIG_CTRL_IFACE_UDP
137 #endif /* !CONFIG_CTRL_IFACE_UDP */
142 #ifdef CONFIG_CTRL_IFACE_UDP
143 ctrl_conn = wpa_ctrl_open(ifname);
145 #else /* CONFIG_CTRL_IFACE_UDP */
146 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
147 cfile = malloc(flen);
150 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
152 if (client_socket_dir && client_socket_dir[0] &&
153 access(client_socket_dir, F_OK) < 0) {
154 perror(client_socket_dir);
159 ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
162 #endif /* CONFIG_CTRL_IFACE_UDP */
166 static void hostapd_cli_close_connection(void)
168 if (ctrl_conn == NULL)
171 if (hostapd_cli_attached) {
172 wpa_ctrl_detach(ctrl_conn);
173 hostapd_cli_attached = 0;
175 wpa_ctrl_close(ctrl_conn);
180 static void hostapd_cli_msg_cb(char *msg, size_t len)
186 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
192 if (ctrl_conn == NULL) {
193 printf("Not connected to hostapd - command dropped.\n");
196 len = sizeof(buf) - 1;
197 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
200 printf("'%s' command timed out.\n", cmd);
202 } else if (ret < 0) {
203 printf("'%s' command failed.\n", cmd);
214 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
216 return _wpa_ctrl_command(ctrl, cmd, 1);
220 static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
229 res = os_snprintf(pos, end - pos, "%s", cmd);
230 if (os_snprintf_error(end - pos, res))
234 for (i = 0; i < argc; i++) {
235 res = os_snprintf(pos, end - pos, " %s", argv[i]);
236 if (os_snprintf_error(end - pos, res))
241 buf[buflen - 1] = '\0';
245 printf("Too long command\n");
250 static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
251 int min_args, int argc, char *argv[])
255 if (argc < min_args) {
256 printf("Invalid %s command - at least %d argument%s required.\n",
257 cmd, min_args, min_args > 1 ? "s are" : " is");
260 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
262 return wpa_ctrl_command(ctrl, buf);
266 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
268 return wpa_ctrl_command(ctrl, "PING");
272 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
274 return wpa_ctrl_command(ctrl, "RELOG");
278 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
280 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
281 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
282 return wpa_ctrl_command(ctrl, "STATUS");
286 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
290 os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
291 return wpa_ctrl_command(ctrl, buf);
293 return wpa_ctrl_command(ctrl, "MIB");
297 static int hostapd_cli_exec(const char *program, const char *arg1,
304 len = os_strlen(arg1) + os_strlen(arg2) + 2;
305 arg = os_malloc(len);
308 os_snprintf(arg, len, "%s %s", arg1, arg2);
309 res = os_exec(program, arg, 1);
316 static void hostapd_cli_action_process(char *msg, size_t len)
322 pos = os_strchr(pos, '>');
329 hostapd_cli_exec(action_file, ctrl_ifname, pos);
333 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
337 printf("Invalid 'sta' command - at least one argument, STA "
338 "address, is required.\n");
342 snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
344 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
345 return wpa_ctrl_command(ctrl, buf);
349 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
354 printf("Invalid 'new_sta' command - exactly one argument, STA "
355 "address, is required.\n");
358 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
359 return wpa_ctrl_command(ctrl, buf);
363 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
368 printf("Invalid 'deauthenticate' command - exactly one "
369 "argument, STA address, is required.\n");
373 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
376 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
377 return wpa_ctrl_command(ctrl, buf);
381 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
386 printf("Invalid 'disassociate' command - exactly one "
387 "argument, STA address, is required.\n");
391 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
394 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
395 return wpa_ctrl_command(ctrl, buf);
399 #ifdef CONFIG_IEEE80211W
400 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
405 printf("Invalid 'sa_query' command - exactly one argument, "
406 "STA address, is required.\n");
409 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
410 return wpa_ctrl_command(ctrl, buf);
412 #endif /* CONFIG_IEEE80211W */
416 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
421 printf("Invalid 'wps_pin' command - at least two arguments, "
422 "UUID and PIN, are required.\n");
426 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
427 argv[0], argv[1], argv[2], argv[3]);
429 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
430 argv[0], argv[1], argv[2]);
432 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
433 return wpa_ctrl_command(ctrl, buf);
437 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
443 if (argc != 1 && argc != 2) {
444 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
445 "- PIN to be verified\n");
450 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
453 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
455 if (os_snprintf_error(sizeof(cmd), res)) {
456 printf("Too long WPS_CHECK_PIN command.\n");
459 return wpa_ctrl_command(ctrl, cmd);
463 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
466 return wpa_ctrl_command(ctrl, "WPS_PBC");
470 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
473 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
477 #ifdef CONFIG_WPS_NFC
478 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
486 printf("Invalid 'wps_nfc_tag_read' command - one argument "
491 buflen = 18 + os_strlen(argv[0]);
492 buf = os_malloc(buflen);
495 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
497 ret = wpa_ctrl_command(ctrl, buf);
504 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
505 int argc, char *argv[])
511 printf("Invalid 'wps_nfc_config_token' command - one argument "
516 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
518 if (os_snprintf_error(sizeof(cmd), res)) {
519 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
522 return wpa_ctrl_command(ctrl, cmd);
526 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
527 int argc, char *argv[])
533 printf("Invalid 'wps_nfc_token' command - one argument is "
538 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
539 if (os_snprintf_error(sizeof(cmd), res)) {
540 printf("Too long WPS_NFC_TOKEN command.\n");
543 return wpa_ctrl_command(ctrl, cmd);
547 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
548 int argc, char *argv[])
554 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
559 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
561 if (os_snprintf_error(sizeof(cmd), res)) {
562 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
565 return wpa_ctrl_command(ctrl, cmd);
568 #endif /* CONFIG_WPS_NFC */
571 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
576 printf("Invalid 'wps_ap_pin' command - at least one argument "
581 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
582 argv[0], argv[1], argv[2]);
584 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
587 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
588 return wpa_ctrl_command(ctrl, buf);
592 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
595 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
599 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
603 char ssid_hex[2 * SSID_MAX_LEN + 1];
604 char key_hex[2 * 64 + 1];
608 printf("Invalid 'wps_config' command - at least two arguments "
614 for (i = 0; i < SSID_MAX_LEN; i++) {
615 if (argv[0][i] == '\0')
617 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
622 for (i = 0; i < 64; i++) {
623 if (argv[3][i] == '\0')
625 os_snprintf(&key_hex[i * 2], 3, "%02x",
631 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
632 ssid_hex, argv[1], argv[2], key_hex);
634 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
635 ssid_hex, argv[1], argv[2]);
637 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
639 return wpa_ctrl_command(ctrl, buf);
641 #endif /* CONFIG_WPS */
644 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
651 printf("Invalid 'disassoc_imminent' command - two arguments "
652 "(STA addr and Disassociation Timer) are needed\n");
656 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
658 if (os_snprintf_error(sizeof(buf), res))
660 return wpa_ctrl_command(ctrl, buf);
664 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
671 printf("Invalid 'ess_disassoc' command - three arguments (STA "
672 "addr, disassoc timer, and URL) are needed\n");
676 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
677 argv[0], argv[1], argv[2]);
678 if (os_snprintf_error(sizeof(buf), res))
680 return wpa_ctrl_command(ctrl, buf);
684 static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
687 char buf[2000], *tmp;
691 printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
695 res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
696 if (os_snprintf_error(sizeof(buf), res))
700 for (i = 1; i < argc; i++) {
702 res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
703 if (os_snprintf_error(sizeof(buf) - total, res))
707 return wpa_ctrl_command(ctrl, buf);
711 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
714 return wpa_ctrl_command(ctrl, "GET_CONFIG");
718 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
719 char *addr, size_t addr_len)
721 char buf[4096], *pos;
725 if (ctrl_conn == NULL) {
726 printf("Not connected to hostapd - command dropped.\n");
729 len = sizeof(buf) - 1;
730 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
733 printf("'%s' command timed out.\n", cmd);
735 } else if (ret < 0) {
736 printf("'%s' command failed.\n", cmd);
741 if (memcmp(buf, "FAIL", 4) == 0)
746 while (*pos != '\0' && *pos != '\n')
749 os_strlcpy(addr, buf, addr_len);
754 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
757 char addr[32], cmd[64];
759 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
762 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
763 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
769 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
771 print_help(stdout, argc > 0 ? argv[0] : NULL);
776 static char ** hostapd_cli_complete_help(const char *str, int pos)
778 int arg = get_cmd_arg_num(str, pos);
783 res = list_cmd_list();
791 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
794 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
799 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
800 int argc, char *argv[])
806 printf("Invalid 'set_qos_map_set' command - "
807 "one argument (comma delimited QoS map set) "
812 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
813 if (os_snprintf_error(sizeof(buf), res))
815 return wpa_ctrl_command(ctrl, buf);
819 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
820 int argc, char *argv[])
826 printf("Invalid 'send_qos_map_conf' command - "
827 "one argument (STA addr) is needed\n");
831 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
832 if (os_snprintf_error(sizeof(buf), res))
834 return wpa_ctrl_command(ctrl, buf);
838 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
845 printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
846 "addr and URL) are needed\n");
850 res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
852 if (os_snprintf_error(sizeof(buf), res))
854 return wpa_ctrl_command(ctrl, buf);
858 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
865 printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
870 res = os_snprintf(buf, sizeof(buf),
871 "HS20_DEAUTH_REQ %s %s %s %s",
872 argv[0], argv[1], argv[2], argv[3]);
874 res = os_snprintf(buf, sizeof(buf),
875 "HS20_DEAUTH_REQ %s %s %s",
876 argv[0], argv[1], argv[2]);
877 if (os_snprintf_error(sizeof(buf), res))
879 return wpa_ctrl_command(ctrl, buf);
883 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
885 hostapd_cli_quit = 1;
892 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
896 printf("Invalid LEVEL command: needs one argument (debug "
900 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
901 return wpa_ctrl_command(ctrl, cmd);
905 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
910 dir = opendir(ctrl_iface_dir);
912 printf("Control interface directory '%s' could not be "
913 "openned.\n", ctrl_iface_dir);
917 printf("Available interfaces:\n");
918 while ((dent = readdir(dir))) {
919 if (strcmp(dent->d_name, ".") == 0 ||
920 strcmp(dent->d_name, "..") == 0)
922 printf("%s\n", dent->d_name);
928 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
932 hostapd_cli_list_interfaces(ctrl);
936 hostapd_cli_close_connection();
937 os_free(ctrl_ifname);
938 ctrl_ifname = os_strdup(argv[0]);
939 if (ctrl_ifname == NULL)
942 if (hostapd_cli_open_connection(ctrl_ifname)) {
943 printf("Connected to interface '%s.\n", ctrl_ifname);
944 if (wpa_ctrl_attach(ctrl_conn) == 0) {
945 hostapd_cli_attached = 1;
947 printf("Warning: Failed to attach to "
951 printf("Could not connect to interface '%s' - re-trying\n",
958 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
964 printf("Invalid SET command: needs two arguments (variable "
965 "name and value)\n");
969 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
970 if (os_snprintf_error(sizeof(cmd), res)) {
971 printf("Too long SET command.\n");
974 return wpa_ctrl_command(ctrl, cmd);
978 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
984 printf("Invalid GET command: needs one argument (variable "
989 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
990 if (os_snprintf_error(sizeof(cmd), res)) {
991 printf("Too long GET command.\n");
994 return wpa_ctrl_command(ctrl, cmd);
999 static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
1007 printf("FST command: parameters are required.\n");
1011 total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
1013 for (i = 0; i < argc; i++) {
1014 res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
1016 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1017 printf("Too long fst command.\n");
1022 return wpa_ctrl_command(ctrl, cmd);
1024 #endif /* CONFIG_FST */
1027 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
1028 int argc, char *argv[])
1037 printf("Invalid chan_switch command: needs at least two "
1038 "arguments (count and freq)\n"
1039 "usage: <cs_count> <freq> [sec_channel_offset=] "
1040 "[center_freq1=] [center_freq2=] [bandwidth=] "
1041 "[blocktx] [ht|vht]\n");
1045 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
1047 if (os_snprintf_error(sizeof(cmd), res)) {
1048 printf("Too long CHAN_SWITCH command.\n");
1053 for (i = 2; i < argc; i++) {
1055 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
1056 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1057 printf("Too long CHAN_SWITCH command.\n");
1062 return wpa_ctrl_command(ctrl, cmd);
1066 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
1069 return wpa_ctrl_command(ctrl, "ENABLE");
1073 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
1076 return wpa_ctrl_command(ctrl, "RELOAD");
1080 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
1083 return wpa_ctrl_command(ctrl, "DISABLE");
1087 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
1092 if (argc < 2 || argc > 3) {
1093 printf("Invalid vendor command\n"
1094 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
1098 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
1099 argc == 3 ? argv[2] : "");
1100 if (os_snprintf_error(sizeof(cmd), res)) {
1101 printf("Too long VENDOR command.\n");
1104 return wpa_ctrl_command(ctrl, cmd);
1108 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1111 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1115 static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
1121 res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
1122 argc >= 1 ? " " : "",
1123 argc >= 1 ? argv[0] : "",
1124 argc == 2 ? " " : "",
1125 argc == 2 ? argv[1] : "");
1126 if (os_snprintf_error(sizeof(cmd), res)) {
1127 printf("Too long option\n");
1130 return wpa_ctrl_command(ctrl, cmd);
1134 static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
1138 return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
1142 static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1144 return wpa_ctrl_command(ctrl, "PMKSA");
1148 static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
1151 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
1155 static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
1161 if (argc < 3 || argc > 5) {
1162 printf("Invalid set_neighbor command: needs 3-5 arguments\n");
1166 res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
1167 argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
1168 argc == 5 ? argv[4] : "");
1169 if (os_snprintf_error(sizeof(cmd), res)) {
1170 printf("Too long SET_NEIGHBOR command.\n");
1173 return wpa_ctrl_command(ctrl, cmd);
1177 static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
1184 printf("Invalid remove_neighbor command: needs 2 arguments\n");
1188 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
1190 if (os_snprintf_error(sizeof(cmd), res)) {
1191 printf("Too long REMOVE_NEIGHBOR command.\n");
1194 return wpa_ctrl_command(ctrl, cmd);
1198 static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
1205 printf("Invalid req_lci command - requires destination address\n");
1209 res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
1210 if (os_snprintf_error(sizeof(cmd), res)) {
1211 printf("Too long REQ_LCI command.\n");
1214 return wpa_ctrl_command(ctrl, cmd);
1218 static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
1222 printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
1226 return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
1230 static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
1233 return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
1237 struct hostapd_cli_cmd {
1239 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1240 char ** (*completion)(const char *str, int pos);
1244 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1245 { "ping", hostapd_cli_cmd_ping, NULL,
1246 "= pings hostapd" },
1247 { "mib", hostapd_cli_cmd_mib, NULL,
1248 "= get MIB variables (dot1x, dot11, radius)" },
1249 { "relog", hostapd_cli_cmd_relog, NULL, NULL },
1250 { "status", hostapd_cli_cmd_status, NULL, NULL },
1251 { "sta", hostapd_cli_cmd_sta, NULL,
1252 "<addr> = get MIB variables for one station" },
1253 { "all_sta", hostapd_cli_cmd_all_sta, NULL,
1254 "= get MIB variables for all stations" },
1255 { "new_sta", hostapd_cli_cmd_new_sta, NULL,
1256 "<addr> = add a new station" },
1257 { "deauthenticate", hostapd_cli_cmd_deauthenticate, NULL,
1258 "<addr> = deauthenticate a station" },
1259 { "disassociate", hostapd_cli_cmd_disassociate, NULL,
1260 "<addr> = disassociate a station" },
1261 #ifdef CONFIG_IEEE80211W
1262 { "sa_query", hostapd_cli_cmd_sa_query, NULL,
1263 "<addr> = send SA Query to a station" },
1264 #endif /* CONFIG_IEEE80211W */
1266 { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
1267 "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
1268 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
1269 "<PIN> = verify PIN checksum" },
1270 { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
1271 "= indicate button pushed to initiate PBC" },
1272 { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
1273 "= cancel the pending WPS operation" },
1274 #ifdef CONFIG_WPS_NFC
1275 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
1276 "<hexdump> = report read NFC tag with WPS data" },
1277 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
1278 "<WPS/NDEF> = build NFC configuration token" },
1279 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
1280 "<WPS/NDEF/enable/disable> = manager NFC password token" },
1281 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
1283 #endif /* CONFIG_WPS_NFC */
1284 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
1285 "<cmd> [params..] = enable/disable AP PIN" },
1286 { "wps_config", hostapd_cli_cmd_wps_config, NULL,
1287 "<SSID> <auth> <encr> <key> = configure AP" },
1288 { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
1289 "= show current WPS status" },
1290 #endif /* CONFIG_WPS */
1291 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
1292 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
1293 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
1294 { "get_config", hostapd_cli_cmd_get_config, NULL,
1295 "= show current configuration" },
1296 { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
1297 "= show this usage help" },
1298 { "interface", hostapd_cli_cmd_interface, NULL,
1299 "[ifname] = show interfaces/select interface" },
1301 { "fst", hostapd_cli_cmd_fst, NULL, NULL },
1302 #endif /* CONFIG_FST */
1303 { "raw", hostapd_cli_cmd_raw, NULL, NULL },
1304 { "level", hostapd_cli_cmd_level, NULL,
1305 "<debug level> = change debug level" },
1306 { "license", hostapd_cli_cmd_license, NULL,
1307 "= show full hostapd_cli license" },
1308 { "quit", hostapd_cli_cmd_quit, NULL,
1309 "= exit hostapd_cli" },
1310 { "set", hostapd_cli_cmd_set, NULL, NULL },
1311 { "get", hostapd_cli_cmd_get, NULL, NULL },
1312 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
1313 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
1314 { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
1315 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
1316 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
1317 { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
1318 { "enable", hostapd_cli_cmd_enable, NULL, NULL },
1319 { "reload", hostapd_cli_cmd_reload, NULL, NULL },
1320 { "disable", hostapd_cli_cmd_disable, NULL, NULL },
1321 { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
1322 { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
1323 { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
1324 { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
1325 { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
1326 { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
1327 { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
1328 { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
1329 { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
1330 { NULL, NULL, NULL, NULL }
1335 * Prints command usage, lines are padded with the specified string.
1337 static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
1343 if (cmd->usage == NULL)
1345 fprintf(stream, "%s%s ", pad, cmd->cmd);
1346 for (n = 0; (c = cmd->usage[n]); n++) {
1347 fprintf(stream, "%c", c);
1349 fprintf(stream, "%s", pad);
1351 fprintf(stream, "\n");
1355 static void print_help(FILE *stream, const char *cmd)
1359 fprintf(stream, "commands:\n");
1360 for (n = 0; hostapd_cli_commands[n].cmd; n++) {
1361 if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
1362 print_cmd_help(stream, &hostapd_cli_commands[n], " ");
1367 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1369 const struct hostapd_cli_cmd *cmd, *match = NULL;
1373 cmd = hostapd_cli_commands;
1375 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1377 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1378 /* we have an exact match */
1388 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1389 cmd = hostapd_cli_commands;
1391 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1393 printf(" %s", cmd->cmd);
1398 } else if (count == 0) {
1399 printf("Unknown command '%s'\n", argv[0]);
1401 match->handler(ctrl, argc - 1, &argv[1]);
1406 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1410 if (ctrl_conn == NULL)
1412 while (wpa_ctrl_pending(ctrl)) {
1414 size_t len = sizeof(buf) - 1;
1415 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1418 hostapd_cli_action_process(buf, len);
1420 if (in_read && first)
1423 printf("%s\n", buf);
1426 printf("Could not read pending message.\n");
1435 static int tokenize_cmd(char *cmd, char *argv[])
1448 if (argc == max_args)
1451 char *pos2 = os_strrchr(pos, '"');
1455 while (*pos != '\0' && *pos != ' ')
1465 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1467 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1468 printf("Connection to hostapd lost - trying to reconnect\n");
1469 hostapd_cli_close_connection();
1472 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1474 printf("Connection to hostapd re-established\n");
1475 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1476 hostapd_cli_attached = 1;
1478 printf("Warning: Failed to attach to "
1484 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1485 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1489 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1495 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1497 char *argv[max_args];
1499 argc = tokenize_cmd(cmd, argv);
1501 wpa_request(ctrl_conn, argc, argv);
1505 static void hostapd_cli_edit_eof_cb(void *ctx)
1511 static char ** list_cmd_list(void)
1516 count = ARRAY_SIZE(hostapd_cli_commands);
1517 res = os_calloc(count + 1, sizeof(char *));
1521 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1522 res[i] = os_strdup(hostapd_cli_commands[i].cmd);
1531 static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
1536 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1537 if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
1539 if (hostapd_cli_commands[i].completion)
1540 return hostapd_cli_commands[i].completion(str, pos);
1541 if (!hostapd_cli_commands[i].usage)
1544 printf("\r%s\n", hostapd_cli_commands[i].usage);
1553 static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
1560 end = os_strchr(str, ' ');
1561 if (end == NULL || str + pos < end)
1562 return list_cmd_list();
1564 cmd = os_malloc(pos + 1);
1567 os_memcpy(cmd, str, pos);
1568 cmd[end - str] = '\0';
1569 res = hostapd_cli_cmd_completion(cmd, str, pos);
1575 static void hostapd_cli_interactive(void)
1577 printf("\nInteractive mode\n\n");
1579 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1580 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1581 hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
1582 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1586 edit_deinit(NULL, NULL);
1587 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1591 static void hostapd_cli_cleanup(void)
1593 hostapd_cli_close_connection();
1595 os_daemonize_terminate(pid_file);
1597 os_program_deinit();
1601 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1609 fd = wpa_ctrl_get_fd(ctrl);
1611 while (!hostapd_cli_quit) {
1614 tv.tv_sec = ping_interval;
1616 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1617 if (res < 0 && errno != EINTR) {
1622 if (FD_ISSET(fd, &rfds))
1623 hostapd_cli_recv_pending(ctrl, 0, 1);
1625 len = sizeof(buf) - 1;
1626 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1627 hostapd_cli_action_process) < 0 ||
1628 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1629 printf("hostapd did not reply to PING "
1630 "command - exiting\n");
1638 int main(int argc, char *argv[])
1640 int warning_displayed = 0;
1644 if (os_program_init())
1648 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1653 action_file = optarg;
1659 ping_interval = atoi(optarg);
1665 printf("%s\n", hostapd_cli_version);
1668 os_free(ctrl_ifname);
1669 ctrl_ifname = os_strdup(optarg);
1672 ctrl_iface_dir = optarg;
1678 client_socket_dir = optarg;
1686 interactive = (argc == optind) && (action_file == NULL);
1689 printf("%s\n\n%s\n\n", hostapd_cli_version,
1690 hostapd_cli_license);
1697 if (ctrl_ifname == NULL) {
1698 struct dirent *dent;
1699 DIR *dir = opendir(ctrl_iface_dir);
1701 while ((dent = readdir(dir))) {
1702 if (os_strcmp(dent->d_name, ".") == 0
1704 os_strcmp(dent->d_name, "..") == 0)
1706 printf("Selected interface '%s'\n",
1708 ctrl_ifname = os_strdup(dent->d_name);
1714 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1716 if (warning_displayed)
1717 printf("Connection established.\n");
1722 perror("Failed to connect to hostapd - "
1727 if (!warning_displayed) {
1728 printf("Could not connect to hostapd - re-trying\n");
1729 warning_displayed = 1;
1735 if (interactive || action_file) {
1736 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1737 hostapd_cli_attached = 1;
1739 printf("Warning: Failed to attach to hostapd.\n");
1745 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1749 hostapd_cli_interactive();
1750 else if (action_file)
1751 hostapd_cli_action(ctrl_conn);
1753 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1755 os_free(ctrl_ifname);
1757 hostapd_cli_cleanup();
1761 #else /* CONFIG_NO_CTRL_IFACE */
1763 int main(int argc, char *argv[])
1768 #endif /* CONFIG_NO_CTRL_IFACE */