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 void print_help(FILE *stream, const char *cmd);
80 static char ** list_cmd_list(void);
81 static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx);
84 static void usage(void)
86 fprintf(stderr, "%s\n", hostapd_cli_version);
89 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
91 " [-P<pid file>] [-G<ping interval>] [command..]\n"
94 " -h help (show this usage text)\n"
95 " -v shown version information\n"
96 " -p<path> path to find control sockets (default: "
98 " -s<dir_path> dir path to open client sockets (default: "
99 CONFIG_CTRL_IFACE_DIR ")\n"
100 " -a<file> run in daemon mode executing the action file "
103 " -B run a daemon in the background\n"
104 " -i<ifname> Interface to listen on (default: first "
105 "interface found in the\n"
106 " socket path)\n\n");
107 print_help(stderr, NULL);
111 static int get_cmd_arg_num(const char *str, int pos)
115 for (i = 0; i <= pos; i++) {
118 while (i <= pos && str[i] != ' ')
129 static int str_starts(const char *src, const char *match)
131 return os_strncmp(src, match, os_strlen(match)) == 0;
135 static void register_event_handler(struct wpa_ctrl *ctrl)
140 event_handler_registered =
141 !eloop_register_read_sock(wpa_ctrl_get_fd(ctrl),
148 static void unregister_event_handler(struct wpa_ctrl *ctrl)
152 if (interactive && event_handler_registered) {
153 eloop_unregister_read_sock(wpa_ctrl_get_fd(ctrl));
154 event_handler_registered = 0;
159 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
161 #ifndef CONFIG_CTRL_IFACE_UDP
164 #endif /* !CONFIG_CTRL_IFACE_UDP */
169 #ifdef CONFIG_CTRL_IFACE_UDP
170 ctrl_conn = wpa_ctrl_open(ifname);
172 #else /* CONFIG_CTRL_IFACE_UDP */
173 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
174 cfile = malloc(flen);
177 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
179 if (client_socket_dir && client_socket_dir[0] &&
180 access(client_socket_dir, F_OK) < 0) {
181 perror(client_socket_dir);
186 ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
189 #endif /* CONFIG_CTRL_IFACE_UDP */
193 static void hostapd_cli_close_connection(void)
195 if (ctrl_conn == NULL)
198 unregister_event_handler(ctrl_conn);
199 if (hostapd_cli_attached) {
200 wpa_ctrl_detach(ctrl_conn);
201 hostapd_cli_attached = 0;
203 wpa_ctrl_close(ctrl_conn);
208 static void hostapd_cli_msg_cb(char *msg, size_t len)
214 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
220 if (ctrl_conn == NULL) {
221 printf("Not connected to hostapd - command dropped.\n");
224 len = sizeof(buf) - 1;
225 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
228 printf("'%s' command timed out.\n", cmd);
230 } else if (ret < 0) {
231 printf("'%s' command failed.\n", cmd);
242 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
244 return _wpa_ctrl_command(ctrl, cmd, 1);
248 static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
257 res = os_snprintf(pos, end - pos, "%s", cmd);
258 if (os_snprintf_error(end - pos, res))
262 for (i = 0; i < argc; i++) {
263 res = os_snprintf(pos, end - pos, " %s", argv[i]);
264 if (os_snprintf_error(end - pos, res))
269 buf[buflen - 1] = '\0';
273 printf("Too long command\n");
278 static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
279 int min_args, int argc, char *argv[])
283 if (argc < min_args) {
284 printf("Invalid %s command - at least %d argument%s required.\n",
285 cmd, min_args, min_args > 1 ? "s are" : " is");
288 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
290 return wpa_ctrl_command(ctrl, buf);
294 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
296 return wpa_ctrl_command(ctrl, "PING");
300 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
302 return wpa_ctrl_command(ctrl, "RELOG");
306 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
308 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
309 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
310 return wpa_ctrl_command(ctrl, "STATUS");
314 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
318 os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
319 return wpa_ctrl_command(ctrl, buf);
321 return wpa_ctrl_command(ctrl, "MIB");
325 static int hostapd_cli_exec(const char *program, const char *arg1,
332 len = os_strlen(arg1) + os_strlen(arg2) + 2;
333 arg = os_malloc(len);
336 os_snprintf(arg, len, "%s %s", arg1, arg2);
337 res = os_exec(program, arg, 1);
344 static void hostapd_cli_action_process(char *msg, size_t len)
350 pos = os_strchr(pos, '>');
357 hostapd_cli_exec(action_file, ctrl_ifname, pos);
361 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
365 printf("Invalid 'sta' command - at least one argument, STA "
366 "address, is required.\n");
370 snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
372 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
373 return wpa_ctrl_command(ctrl, buf);
377 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
382 printf("Invalid 'new_sta' command - exactly one argument, STA "
383 "address, is required.\n");
386 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
387 return wpa_ctrl_command(ctrl, buf);
391 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
396 printf("Invalid 'deauthenticate' command - exactly one "
397 "argument, STA address, is required.\n");
401 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
404 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
405 return wpa_ctrl_command(ctrl, buf);
409 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
414 printf("Invalid 'disassociate' command - exactly one "
415 "argument, STA address, is required.\n");
419 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
422 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
423 return wpa_ctrl_command(ctrl, buf);
427 #ifdef CONFIG_IEEE80211W
428 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
433 printf("Invalid 'sa_query' command - exactly one argument, "
434 "STA address, is required.\n");
437 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
438 return wpa_ctrl_command(ctrl, buf);
440 #endif /* CONFIG_IEEE80211W */
444 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
449 printf("Invalid 'wps_pin' command - at least two arguments, "
450 "UUID and PIN, are required.\n");
454 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
455 argv[0], argv[1], argv[2], argv[3]);
457 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
458 argv[0], argv[1], argv[2]);
460 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
461 return wpa_ctrl_command(ctrl, buf);
465 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
471 if (argc != 1 && argc != 2) {
472 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
473 "- PIN to be verified\n");
478 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
481 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
483 if (os_snprintf_error(sizeof(cmd), res)) {
484 printf("Too long WPS_CHECK_PIN command.\n");
487 return wpa_ctrl_command(ctrl, cmd);
491 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
494 return wpa_ctrl_command(ctrl, "WPS_PBC");
498 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
501 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
505 #ifdef CONFIG_WPS_NFC
506 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
514 printf("Invalid 'wps_nfc_tag_read' command - one argument "
519 buflen = 18 + os_strlen(argv[0]);
520 buf = os_malloc(buflen);
523 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
525 ret = wpa_ctrl_command(ctrl, buf);
532 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
533 int argc, char *argv[])
539 printf("Invalid 'wps_nfc_config_token' command - one argument "
544 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
546 if (os_snprintf_error(sizeof(cmd), res)) {
547 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
550 return wpa_ctrl_command(ctrl, cmd);
554 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
555 int argc, char *argv[])
561 printf("Invalid 'wps_nfc_token' command - one argument is "
566 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
567 if (os_snprintf_error(sizeof(cmd), res)) {
568 printf("Too long WPS_NFC_TOKEN command.\n");
571 return wpa_ctrl_command(ctrl, cmd);
575 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
576 int argc, char *argv[])
582 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
587 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
589 if (os_snprintf_error(sizeof(cmd), res)) {
590 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
593 return wpa_ctrl_command(ctrl, cmd);
596 #endif /* CONFIG_WPS_NFC */
599 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
604 printf("Invalid 'wps_ap_pin' command - at least one argument "
609 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
610 argv[0], argv[1], argv[2]);
612 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
615 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
616 return wpa_ctrl_command(ctrl, buf);
620 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
623 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
627 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
631 char ssid_hex[2 * SSID_MAX_LEN + 1];
632 char key_hex[2 * 64 + 1];
636 printf("Invalid 'wps_config' command - at least two arguments "
642 for (i = 0; i < SSID_MAX_LEN; i++) {
643 if (argv[0][i] == '\0')
645 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
650 for (i = 0; i < 64; i++) {
651 if (argv[3][i] == '\0')
653 os_snprintf(&key_hex[i * 2], 3, "%02x",
659 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
660 ssid_hex, argv[1], argv[2], key_hex);
662 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
663 ssid_hex, argv[1], argv[2]);
665 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
667 return wpa_ctrl_command(ctrl, buf);
669 #endif /* CONFIG_WPS */
672 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
679 printf("Invalid 'disassoc_imminent' command - two arguments "
680 "(STA addr and Disassociation Timer) are needed\n");
684 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
686 if (os_snprintf_error(sizeof(buf), res))
688 return wpa_ctrl_command(ctrl, buf);
692 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
699 printf("Invalid 'ess_disassoc' command - three arguments (STA "
700 "addr, disassoc timer, and URL) are needed\n");
704 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
705 argv[0], argv[1], argv[2]);
706 if (os_snprintf_error(sizeof(buf), res))
708 return wpa_ctrl_command(ctrl, buf);
712 static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
715 char buf[2000], *tmp;
719 printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
723 res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
724 if (os_snprintf_error(sizeof(buf), res))
728 for (i = 1; i < argc; i++) {
730 res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
731 if (os_snprintf_error(sizeof(buf) - total, res))
735 return wpa_ctrl_command(ctrl, buf);
739 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
742 return wpa_ctrl_command(ctrl, "GET_CONFIG");
746 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
747 char *addr, size_t addr_len)
749 char buf[4096], *pos;
753 if (ctrl_conn == NULL) {
754 printf("Not connected to hostapd - command dropped.\n");
757 len = sizeof(buf) - 1;
758 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
761 printf("'%s' command timed out.\n", cmd);
763 } else if (ret < 0) {
764 printf("'%s' command failed.\n", cmd);
769 if (memcmp(buf, "FAIL", 4) == 0)
774 while (*pos != '\0' && *pos != '\n')
777 os_strlcpy(addr, buf, addr_len);
782 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
785 char addr[32], cmd[64];
787 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
790 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
791 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
797 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
799 print_help(stdout, argc > 0 ? argv[0] : NULL);
804 static char ** hostapd_cli_complete_help(const char *str, int pos)
806 int arg = get_cmd_arg_num(str, pos);
811 res = list_cmd_list();
819 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
822 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
827 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
828 int argc, char *argv[])
834 printf("Invalid 'set_qos_map_set' command - "
835 "one argument (comma delimited QoS map set) "
840 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
841 if (os_snprintf_error(sizeof(buf), res))
843 return wpa_ctrl_command(ctrl, buf);
847 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
848 int argc, char *argv[])
854 printf("Invalid 'send_qos_map_conf' command - "
855 "one argument (STA addr) is needed\n");
859 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
860 if (os_snprintf_error(sizeof(buf), res))
862 return wpa_ctrl_command(ctrl, buf);
866 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
873 printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
874 "addr and URL) are needed\n");
878 res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
880 if (os_snprintf_error(sizeof(buf), res))
882 return wpa_ctrl_command(ctrl, buf);
886 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
893 printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
898 res = os_snprintf(buf, sizeof(buf),
899 "HS20_DEAUTH_REQ %s %s %s %s",
900 argv[0], argv[1], argv[2], argv[3]);
902 res = os_snprintf(buf, sizeof(buf),
903 "HS20_DEAUTH_REQ %s %s %s",
904 argv[0], argv[1], argv[2]);
905 if (os_snprintf_error(sizeof(buf), res))
907 return wpa_ctrl_command(ctrl, buf);
911 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
913 hostapd_cli_quit = 1;
920 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
924 printf("Invalid LEVEL command: needs one argument (debug "
928 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
929 return wpa_ctrl_command(ctrl, cmd);
933 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
938 dir = opendir(ctrl_iface_dir);
940 printf("Control interface directory '%s' could not be "
941 "openned.\n", ctrl_iface_dir);
945 printf("Available interfaces:\n");
946 while ((dent = readdir(dir))) {
947 if (strcmp(dent->d_name, ".") == 0 ||
948 strcmp(dent->d_name, "..") == 0)
950 printf("%s\n", dent->d_name);
956 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
960 hostapd_cli_list_interfaces(ctrl);
964 hostapd_cli_close_connection();
965 os_free(ctrl_ifname);
966 ctrl_ifname = os_strdup(argv[0]);
967 if (ctrl_ifname == NULL)
970 if (hostapd_cli_open_connection(ctrl_ifname)) {
971 printf("Connected to interface '%s.\n", ctrl_ifname);
972 if (wpa_ctrl_attach(ctrl_conn) == 0) {
973 hostapd_cli_attached = 1;
974 register_event_handler(ctrl_conn);
976 printf("Warning: Failed to attach to "
980 printf("Could not connect to interface '%s' - re-trying\n",
987 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
993 printf("Invalid SET command: needs two arguments (variable "
994 "name and value)\n");
998 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
999 if (os_snprintf_error(sizeof(cmd), res)) {
1000 printf("Too long SET command.\n");
1003 return wpa_ctrl_command(ctrl, cmd);
1007 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
1013 printf("Invalid GET command: needs one argument (variable "
1018 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
1019 if (os_snprintf_error(sizeof(cmd), res)) {
1020 printf("Too long GET command.\n");
1023 return wpa_ctrl_command(ctrl, cmd);
1028 static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
1036 printf("FST command: parameters are required.\n");
1040 total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
1042 for (i = 0; i < argc; i++) {
1043 res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
1045 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1046 printf("Too long fst command.\n");
1051 return wpa_ctrl_command(ctrl, cmd);
1053 #endif /* CONFIG_FST */
1056 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
1057 int argc, char *argv[])
1066 printf("Invalid chan_switch command: needs at least two "
1067 "arguments (count and freq)\n"
1068 "usage: <cs_count> <freq> [sec_channel_offset=] "
1069 "[center_freq1=] [center_freq2=] [bandwidth=] "
1070 "[blocktx] [ht|vht]\n");
1074 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
1076 if (os_snprintf_error(sizeof(cmd), res)) {
1077 printf("Too long CHAN_SWITCH command.\n");
1082 for (i = 2; i < argc; i++) {
1084 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
1085 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1086 printf("Too long CHAN_SWITCH command.\n");
1091 return wpa_ctrl_command(ctrl, cmd);
1095 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
1098 return wpa_ctrl_command(ctrl, "ENABLE");
1102 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
1105 return wpa_ctrl_command(ctrl, "RELOAD");
1109 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
1112 return wpa_ctrl_command(ctrl, "DISABLE");
1116 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
1121 if (argc < 2 || argc > 3) {
1122 printf("Invalid vendor command\n"
1123 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
1127 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
1128 argc == 3 ? argv[2] : "");
1129 if (os_snprintf_error(sizeof(cmd), res)) {
1130 printf("Too long VENDOR command.\n");
1133 return wpa_ctrl_command(ctrl, cmd);
1137 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1140 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1144 static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
1150 res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
1151 argc >= 1 ? " " : "",
1152 argc >= 1 ? argv[0] : "",
1153 argc == 2 ? " " : "",
1154 argc == 2 ? argv[1] : "");
1155 if (os_snprintf_error(sizeof(cmd), res)) {
1156 printf("Too long option\n");
1159 return wpa_ctrl_command(ctrl, cmd);
1163 static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
1167 return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
1171 static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1173 return wpa_ctrl_command(ctrl, "PMKSA");
1177 static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
1180 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
1184 static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
1190 if (argc < 3 || argc > 5) {
1191 printf("Invalid set_neighbor command: needs 3-5 arguments\n");
1195 res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
1196 argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
1197 argc == 5 ? argv[4] : "");
1198 if (os_snprintf_error(sizeof(cmd), res)) {
1199 printf("Too long SET_NEIGHBOR command.\n");
1202 return wpa_ctrl_command(ctrl, cmd);
1206 static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
1213 printf("Invalid remove_neighbor command: needs 2 arguments\n");
1217 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
1219 if (os_snprintf_error(sizeof(cmd), res)) {
1220 printf("Too long REMOVE_NEIGHBOR command.\n");
1223 return wpa_ctrl_command(ctrl, cmd);
1227 static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
1234 printf("Invalid req_lci command - requires destination address\n");
1238 res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
1239 if (os_snprintf_error(sizeof(cmd), res)) {
1240 printf("Too long REQ_LCI command.\n");
1243 return wpa_ctrl_command(ctrl, cmd);
1247 static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
1251 printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
1255 return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
1259 static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
1262 return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
1266 struct hostapd_cli_cmd {
1268 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1269 char ** (*completion)(const char *str, int pos);
1273 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1274 { "ping", hostapd_cli_cmd_ping, NULL,
1275 "= pings hostapd" },
1276 { "mib", hostapd_cli_cmd_mib, NULL,
1277 "= get MIB variables (dot1x, dot11, radius)" },
1278 { "relog", hostapd_cli_cmd_relog, NULL, NULL },
1279 { "status", hostapd_cli_cmd_status, NULL, NULL },
1280 { "sta", hostapd_cli_cmd_sta, NULL,
1281 "<addr> = get MIB variables for one station" },
1282 { "all_sta", hostapd_cli_cmd_all_sta, NULL,
1283 "= get MIB variables for all stations" },
1284 { "new_sta", hostapd_cli_cmd_new_sta, NULL,
1285 "<addr> = add a new station" },
1286 { "deauthenticate", hostapd_cli_cmd_deauthenticate, NULL,
1287 "<addr> = deauthenticate a station" },
1288 { "disassociate", hostapd_cli_cmd_disassociate, NULL,
1289 "<addr> = disassociate a station" },
1290 #ifdef CONFIG_IEEE80211W
1291 { "sa_query", hostapd_cli_cmd_sa_query, NULL,
1292 "<addr> = send SA Query to a station" },
1293 #endif /* CONFIG_IEEE80211W */
1295 { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
1296 "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
1297 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
1298 "<PIN> = verify PIN checksum" },
1299 { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
1300 "= indicate button pushed to initiate PBC" },
1301 { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
1302 "= cancel the pending WPS operation" },
1303 #ifdef CONFIG_WPS_NFC
1304 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
1305 "<hexdump> = report read NFC tag with WPS data" },
1306 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
1307 "<WPS/NDEF> = build NFC configuration token" },
1308 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
1309 "<WPS/NDEF/enable/disable> = manager NFC password token" },
1310 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
1312 #endif /* CONFIG_WPS_NFC */
1313 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
1314 "<cmd> [params..] = enable/disable AP PIN" },
1315 { "wps_config", hostapd_cli_cmd_wps_config, NULL,
1316 "<SSID> <auth> <encr> <key> = configure AP" },
1317 { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
1318 "= show current WPS status" },
1319 #endif /* CONFIG_WPS */
1320 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
1321 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
1322 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
1323 { "get_config", hostapd_cli_cmd_get_config, NULL,
1324 "= show current configuration" },
1325 { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
1326 "= show this usage help" },
1327 { "interface", hostapd_cli_cmd_interface, NULL,
1328 "[ifname] = show interfaces/select interface" },
1330 { "fst", hostapd_cli_cmd_fst, NULL, NULL },
1331 #endif /* CONFIG_FST */
1332 { "raw", hostapd_cli_cmd_raw, NULL, NULL },
1333 { "level", hostapd_cli_cmd_level, NULL,
1334 "<debug level> = change debug level" },
1335 { "license", hostapd_cli_cmd_license, NULL,
1336 "= show full hostapd_cli license" },
1337 { "quit", hostapd_cli_cmd_quit, NULL,
1338 "= exit hostapd_cli" },
1339 { "set", hostapd_cli_cmd_set, NULL, NULL },
1340 { "get", hostapd_cli_cmd_get, NULL, NULL },
1341 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
1342 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
1343 { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
1344 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
1345 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
1346 { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
1347 { "enable", hostapd_cli_cmd_enable, NULL, NULL },
1348 { "reload", hostapd_cli_cmd_reload, NULL, NULL },
1349 { "disable", hostapd_cli_cmd_disable, NULL, NULL },
1350 { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
1351 { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
1352 { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
1353 { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
1354 { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
1355 { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
1356 { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
1357 { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
1358 { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
1359 { NULL, NULL, NULL, NULL }
1364 * Prints command usage, lines are padded with the specified string.
1366 static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
1372 if (cmd->usage == NULL)
1374 fprintf(stream, "%s%s ", pad, cmd->cmd);
1375 for (n = 0; (c = cmd->usage[n]); n++) {
1376 fprintf(stream, "%c", c);
1378 fprintf(stream, "%s", pad);
1380 fprintf(stream, "\n");
1384 static void print_help(FILE *stream, const char *cmd)
1388 fprintf(stream, "commands:\n");
1389 for (n = 0; hostapd_cli_commands[n].cmd; n++) {
1390 if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
1391 print_cmd_help(stream, &hostapd_cli_commands[n], " ");
1396 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1398 const struct hostapd_cli_cmd *cmd, *match = NULL;
1402 cmd = hostapd_cli_commands;
1404 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1406 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1407 /* we have an exact match */
1417 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1418 cmd = hostapd_cli_commands;
1420 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1422 printf(" %s", cmd->cmd);
1427 } else if (count == 0) {
1428 printf("Unknown command '%s'\n", argv[0]);
1430 match->handler(ctrl, argc - 1, &argv[1]);
1435 static void cli_event(const char *str)
1440 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1444 if (ctrl_conn == NULL)
1446 while (wpa_ctrl_pending(ctrl)) {
1448 size_t len = sizeof(buf) - 1;
1449 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1452 hostapd_cli_action_process(buf, len);
1455 if (in_read && first)
1458 printf("%s\n", buf);
1461 printf("Could not read pending message.\n");
1468 static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx)
1470 hostapd_cli_recv_pending(ctrl_conn, 0, 0);
1476 static int tokenize_cmd(char *cmd, char *argv[])
1489 if (argc == max_args)
1492 char *pos2 = os_strrchr(pos, '"');
1496 while (*pos != '\0' && *pos != ' ')
1506 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1508 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1509 printf("Connection to hostapd lost - trying to reconnect\n");
1510 hostapd_cli_close_connection();
1513 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1515 printf("Connection to hostapd re-established\n");
1516 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1517 hostapd_cli_attached = 1;
1518 register_event_handler(ctrl_conn);
1520 printf("Warning: Failed to attach to "
1526 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1527 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1531 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1537 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1539 char *argv[max_args];
1541 argc = tokenize_cmd(cmd, argv);
1543 wpa_request(ctrl_conn, argc, argv);
1547 static void hostapd_cli_edit_eof_cb(void *ctx)
1553 static char ** list_cmd_list(void)
1558 count = ARRAY_SIZE(hostapd_cli_commands);
1559 res = os_calloc(count + 1, sizeof(char *));
1563 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1564 res[i] = os_strdup(hostapd_cli_commands[i].cmd);
1573 static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
1578 for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1579 if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
1581 if (hostapd_cli_commands[i].completion)
1582 return hostapd_cli_commands[i].completion(str, pos);
1583 if (!hostapd_cli_commands[i].usage)
1586 printf("\r%s\n", hostapd_cli_commands[i].usage);
1595 static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
1602 end = os_strchr(str, ' ');
1603 if (end == NULL || str + pos < end)
1604 return list_cmd_list();
1606 cmd = os_malloc(pos + 1);
1609 os_memcpy(cmd, str, pos);
1610 cmd[end - str] = '\0';
1611 res = hostapd_cli_cmd_completion(cmd, str, pos);
1617 static void hostapd_cli_interactive(void)
1619 printf("\nInteractive mode\n\n");
1621 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1622 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1623 hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
1624 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1628 edit_deinit(NULL, NULL);
1629 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1633 static void hostapd_cli_cleanup(void)
1635 hostapd_cli_close_connection();
1637 os_daemonize_terminate(pid_file);
1639 os_program_deinit();
1643 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1651 fd = wpa_ctrl_get_fd(ctrl);
1653 while (!hostapd_cli_quit) {
1656 tv.tv_sec = ping_interval;
1658 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1659 if (res < 0 && errno != EINTR) {
1664 if (FD_ISSET(fd, &rfds))
1665 hostapd_cli_recv_pending(ctrl, 0, 1);
1667 len = sizeof(buf) - 1;
1668 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1669 hostapd_cli_action_process) < 0 ||
1670 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1671 printf("hostapd did not reply to PING "
1672 "command - exiting\n");
1680 int main(int argc, char *argv[])
1682 int warning_displayed = 0;
1686 if (os_program_init())
1690 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1695 action_file = optarg;
1701 ping_interval = atoi(optarg);
1707 printf("%s\n", hostapd_cli_version);
1710 os_free(ctrl_ifname);
1711 ctrl_ifname = os_strdup(optarg);
1714 ctrl_iface_dir = optarg;
1720 client_socket_dir = optarg;
1728 interactive = (argc == optind) && (action_file == NULL);
1731 printf("%s\n\n%s\n\n", hostapd_cli_version,
1732 hostapd_cli_license);
1739 if (ctrl_ifname == NULL) {
1740 struct dirent *dent;
1741 DIR *dir = opendir(ctrl_iface_dir);
1743 while ((dent = readdir(dir))) {
1744 if (os_strcmp(dent->d_name, ".") == 0
1746 os_strcmp(dent->d_name, "..") == 0)
1748 printf("Selected interface '%s'\n",
1750 ctrl_ifname = os_strdup(dent->d_name);
1756 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1758 if (warning_displayed)
1759 printf("Connection established.\n");
1764 perror("Failed to connect to hostapd - "
1769 if (!warning_displayed) {
1770 printf("Could not connect to hostapd - re-trying\n");
1771 warning_displayed = 1;
1777 if (interactive || action_file) {
1778 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1779 hostapd_cli_attached = 1;
1780 register_event_handler(ctrl_conn);
1782 printf("Warning: Failed to attach to hostapd.\n");
1788 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1792 hostapd_cli_interactive();
1793 else if (action_file)
1794 hostapd_cli_action(ctrl_conn);
1796 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1798 unregister_event_handler(ctrl_conn);
1799 os_free(ctrl_ifname);
1801 hostapd_cli_cleanup();
1805 #else /* CONFIG_NO_CTRL_IFACE */
1807 int main(int argc, char *argv[])
1812 #endif /* CONFIG_NO_CTRL_IFACE */