2 * hostapd - command line interface for hostapd daemon
3 * Copyright (c) 2004-2014, 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 "utils/common.h"
14 #include "utils/eloop.h"
15 #include "utils/edit.h"
16 #include "common/version.h"
19 static const char *hostapd_cli_version =
20 "hostapd_cli v" VERSION_STR "\n"
21 "Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
24 static const char *hostapd_cli_license =
25 "This software may be distributed under the terms of the BSD license.\n"
26 "See README for more details.\n";
28 static const char *hostapd_cli_full_license =
29 "This software may be distributed under the terms of the BSD license.\n"
31 "Redistribution and use in source and binary forms, with or without\n"
32 "modification, are permitted provided that the following conditions are\n"
35 "1. Redistributions of source code must retain the above copyright\n"
36 " notice, this list of conditions and the following disclaimer.\n"
38 "2. Redistributions in binary form must reproduce the above copyright\n"
39 " notice, this list of conditions and the following disclaimer in the\n"
40 " documentation and/or other materials provided with the distribution.\n"
42 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
43 " names of its contributors may be used to endorse or promote products\n"
44 " derived from this software without specific prior written permission.\n"
46 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
47 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
48 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
49 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
50 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
51 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
52 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
53 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
54 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
55 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
56 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
59 static const char *commands_help =
61 " mib get MIB variables (dot1x, dot11, radius)\n"
62 " sta <addr> get MIB variables for one station\n"
63 " all_sta get MIB variables for all stations\n"
64 " new_sta <addr> add a new station\n"
65 " deauthenticate <addr> deauthenticate a station\n"
66 " disassociate <addr> disassociate a station\n"
67 #ifdef CONFIG_IEEE80211W
68 " sa_query <addr> send SA Query to a station\n"
69 #endif /* CONFIG_IEEE80211W */
71 " wps_pin <uuid> <pin> [timeout] [addr] add WPS Enrollee PIN\n"
72 " wps_check_pin <PIN> verify PIN checksum\n"
73 " wps_pbc indicate button pushed to initiate PBC\n"
74 " wps_cancel cancel the pending WPS operation\n"
76 " wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
77 " wps_nfc_config_token <WPS/NDEF> build NFC configuration token\n"
78 " wps_nfc_token <WPS/NDEF/enable/disable> manager NFC password token\n"
79 #endif /* CONFIG_WPS_NFC */
80 " wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
81 " wps_config <SSID> <auth> <encr> <key> configure AP\n"
82 " wps_get_status show current WPS status\n"
83 #endif /* CONFIG_WPS */
84 " get_config show current configuration\n"
85 " help show this usage help\n"
86 " interface [ifname] show interfaces/select interface\n"
87 " level <debug level> change debug level\n"
88 " license show full hostapd_cli license\n"
89 " quit exit hostapd_cli\n";
91 static struct wpa_ctrl *ctrl_conn;
92 static int hostapd_cli_quit = 0;
93 static int hostapd_cli_attached = 0;
95 #ifndef CONFIG_CTRL_IFACE_DIR
96 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
97 #endif /* CONFIG_CTRL_IFACE_DIR */
98 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
100 static char *ctrl_ifname = NULL;
101 static const char *pid_file = NULL;
102 static const char *action_file = NULL;
103 static int ping_interval = 5;
104 static int interactive = 0;
107 static void usage(void)
109 fprintf(stderr, "%s\n", hostapd_cli_version);
112 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
114 " [-G<ping interval>] [command..]\n"
117 " -h help (show this usage text)\n"
118 " -v shown version information\n"
119 " -p<path> path to find control sockets (default: "
120 "/var/run/hostapd)\n"
121 " -a<file> run in daemon mode executing the action file "
124 " -B run a daemon in the background\n"
125 " -i<ifname> Interface to listen on (default: first "
126 "interface found in the\n"
133 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
141 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
142 cfile = malloc(flen);
145 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
147 ctrl_conn = wpa_ctrl_open(cfile);
153 static void hostapd_cli_close_connection(void)
155 if (ctrl_conn == NULL)
158 if (hostapd_cli_attached) {
159 wpa_ctrl_detach(ctrl_conn);
160 hostapd_cli_attached = 0;
162 wpa_ctrl_close(ctrl_conn);
167 static void hostapd_cli_msg_cb(char *msg, size_t len)
173 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
179 if (ctrl_conn == NULL) {
180 printf("Not connected to hostapd - command dropped.\n");
183 len = sizeof(buf) - 1;
184 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
187 printf("'%s' command timed out.\n", cmd);
189 } else if (ret < 0) {
190 printf("'%s' command failed.\n", cmd);
201 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
203 return _wpa_ctrl_command(ctrl, cmd, 1);
207 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
209 return wpa_ctrl_command(ctrl, "PING");
213 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
215 return wpa_ctrl_command(ctrl, "RELOG");
219 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
221 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
222 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
223 return wpa_ctrl_command(ctrl, "STATUS");
227 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
231 os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
232 return wpa_ctrl_command(ctrl, buf);
234 return wpa_ctrl_command(ctrl, "MIB");
238 static int hostapd_cli_exec(const char *program, const char *arg1,
246 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
247 cmd = os_malloc(len);
250 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
251 if (res < 0 || (size_t) res >= len) {
259 #endif /* _WIN32_WCE */
266 static void hostapd_cli_action_process(char *msg, size_t len)
272 pos = os_strchr(pos, '>');
279 hostapd_cli_exec(action_file, ctrl_ifname, pos);
283 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
287 printf("Invalid 'sta' command - at least one argument, STA "
288 "address, is required.\n");
292 snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
294 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
295 return wpa_ctrl_command(ctrl, buf);
299 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
304 printf("Invalid 'new_sta' command - exactly one argument, STA "
305 "address, is required.\n");
308 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
309 return wpa_ctrl_command(ctrl, buf);
313 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
318 printf("Invalid 'deauthenticate' command - exactly one "
319 "argument, STA address, is required.\n");
323 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
326 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
327 return wpa_ctrl_command(ctrl, buf);
331 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
336 printf("Invalid 'disassociate' command - exactly one "
337 "argument, STA address, is required.\n");
341 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
344 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
345 return wpa_ctrl_command(ctrl, buf);
349 #ifdef CONFIG_IEEE80211W
350 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
355 printf("Invalid 'sa_query' command - exactly one argument, "
356 "STA address, is required.\n");
359 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
360 return wpa_ctrl_command(ctrl, buf);
362 #endif /* CONFIG_IEEE80211W */
366 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
371 printf("Invalid 'wps_pin' command - at least two arguments, "
372 "UUID and PIN, are required.\n");
376 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
377 argv[0], argv[1], argv[2], argv[3]);
379 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
380 argv[0], argv[1], argv[2]);
382 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
383 return wpa_ctrl_command(ctrl, buf);
387 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
393 if (argc != 1 && argc != 2) {
394 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
395 "- PIN to be verified\n");
400 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
403 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
405 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
406 printf("Too long WPS_CHECK_PIN command.\n");
409 return wpa_ctrl_command(ctrl, cmd);
413 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
416 return wpa_ctrl_command(ctrl, "WPS_PBC");
420 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
423 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
427 #ifdef CONFIG_WPS_NFC
428 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
436 printf("Invalid 'wps_nfc_tag_read' command - one argument "
441 buflen = 18 + os_strlen(argv[0]);
442 buf = os_malloc(buflen);
445 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
447 ret = wpa_ctrl_command(ctrl, buf);
454 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
455 int argc, char *argv[])
461 printf("Invalid 'wps_nfc_config_token' command - one argument "
466 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
468 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
469 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
472 return wpa_ctrl_command(ctrl, cmd);
476 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
477 int argc, char *argv[])
483 printf("Invalid 'wps_nfc_token' command - one argument is "
488 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
489 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
490 printf("Too long WPS_NFC_TOKEN command.\n");
493 return wpa_ctrl_command(ctrl, cmd);
497 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
498 int argc, char *argv[])
504 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
509 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
511 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
512 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
515 return wpa_ctrl_command(ctrl, cmd);
518 #endif /* CONFIG_WPS_NFC */
521 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
526 printf("Invalid 'wps_ap_pin' command - at least one argument "
531 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
532 argv[0], argv[1], argv[2]);
534 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
537 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
538 return wpa_ctrl_command(ctrl, buf);
542 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
545 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
549 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
553 char ssid_hex[2 * 32 + 1];
554 char key_hex[2 * 64 + 1];
558 printf("Invalid 'wps_config' command - at least two arguments "
564 for (i = 0; i < 32; i++) {
565 if (argv[0][i] == '\0')
567 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
572 for (i = 0; i < 64; i++) {
573 if (argv[3][i] == '\0')
575 os_snprintf(&key_hex[i * 2], 3, "%02x",
581 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
582 ssid_hex, argv[1], argv[2], key_hex);
584 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
585 ssid_hex, argv[1], argv[2]);
587 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
589 return wpa_ctrl_command(ctrl, buf);
591 #endif /* CONFIG_WPS */
594 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
601 printf("Invalid 'disassoc_imminent' command - two arguments "
602 "(STA addr and Disassociation Timer) are needed\n");
606 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
608 if (res < 0 || res >= (int) sizeof(buf))
610 return wpa_ctrl_command(ctrl, buf);
614 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
621 printf("Invalid 'ess_disassoc' command - three arguments (STA "
622 "addr, disassoc timer, and URL) are needed\n");
626 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
627 argv[0], argv[1], argv[2]);
628 if (res < 0 || res >= (int) sizeof(buf))
630 return wpa_ctrl_command(ctrl, buf);
634 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
637 return wpa_ctrl_command(ctrl, "GET_CONFIG");
641 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
642 char *addr, size_t addr_len)
644 char buf[4096], *pos;
648 if (ctrl_conn == NULL) {
649 printf("Not connected to hostapd - command dropped.\n");
652 len = sizeof(buf) - 1;
653 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
656 printf("'%s' command timed out.\n", cmd);
658 } else if (ret < 0) {
659 printf("'%s' command failed.\n", cmd);
664 if (memcmp(buf, "FAIL", 4) == 0)
669 while (*pos != '\0' && *pos != '\n')
672 os_strlcpy(addr, buf, addr_len);
677 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
680 char addr[32], cmd[64];
682 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
685 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
686 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
692 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
694 printf("%s", commands_help);
699 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
702 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
707 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
708 int argc, char *argv[])
714 printf("Invalid 'set_qos_map_set' command - "
715 "one argument (comma delimited QoS map set) "
720 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
721 if (res < 0 || res >= (int) sizeof(buf))
723 return wpa_ctrl_command(ctrl, buf);
727 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
728 int argc, char *argv[])
734 printf("Invalid 'send_qos_map_conf' command - "
735 "one argument (STA addr) is needed\n");
739 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
740 if (res < 0 || res >= (int) sizeof(buf))
742 return wpa_ctrl_command(ctrl, buf);
746 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
753 printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
754 "addr and URL) are needed\n");
758 res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
760 if (res < 0 || res >= (int) sizeof(buf))
762 return wpa_ctrl_command(ctrl, buf);
766 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
773 printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
778 res = os_snprintf(buf, sizeof(buf),
779 "HS20_DEAUTH_REQ %s %s %s %s",
780 argv[0], argv[1], argv[2], argv[3]);
782 res = os_snprintf(buf, sizeof(buf),
783 "HS20_DEAUTH_REQ %s %s %s",
784 argv[0], argv[1], argv[2]);
785 if (res < 0 || res >= (int) sizeof(buf))
787 return wpa_ctrl_command(ctrl, buf);
791 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
793 hostapd_cli_quit = 1;
800 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
804 printf("Invalid LEVEL command: needs one argument (debug "
808 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
809 return wpa_ctrl_command(ctrl, cmd);
813 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
818 dir = opendir(ctrl_iface_dir);
820 printf("Control interface directory '%s' could not be "
821 "openned.\n", ctrl_iface_dir);
825 printf("Available interfaces:\n");
826 while ((dent = readdir(dir))) {
827 if (strcmp(dent->d_name, ".") == 0 ||
828 strcmp(dent->d_name, "..") == 0)
830 printf("%s\n", dent->d_name);
836 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
840 hostapd_cli_list_interfaces(ctrl);
844 hostapd_cli_close_connection();
846 ctrl_ifname = strdup(argv[0]);
848 if (hostapd_cli_open_connection(ctrl_ifname)) {
849 printf("Connected to interface '%s.\n", ctrl_ifname);
850 if (wpa_ctrl_attach(ctrl_conn) == 0) {
851 hostapd_cli_attached = 1;
853 printf("Warning: Failed to attach to "
857 printf("Could not connect to interface '%s' - re-trying\n",
864 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
870 printf("Invalid SET command: needs two arguments (variable "
871 "name and value)\n");
875 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
876 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
877 printf("Too long SET command.\n");
880 return wpa_ctrl_command(ctrl, cmd);
884 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
890 printf("Invalid GET command: needs one argument (variable "
895 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
896 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
897 printf("Too long GET command.\n");
900 return wpa_ctrl_command(ctrl, cmd);
904 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
905 int argc, char *argv[])
914 printf("Invalid chan_switch command: needs at least two "
915 "arguments (count and freq)\n"
916 "usage: <cs_count> <freq> [sec_channel_offset=] "
917 "[center_freq1=] [center_freq2=] [bandwidth=] "
918 "[blocktx] [ht|vht]\n");
922 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
924 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
925 printf("Too long CHAN_SWITCH command.\n");
930 for (i = 2; i < argc; i++) {
932 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
933 if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) {
934 printf("Too long CHAN_SWITCH command.\n");
939 return wpa_ctrl_command(ctrl, cmd);
943 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
948 if (argc < 2 || argc > 3) {
949 printf("Invalid vendor command\n"
950 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
954 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
955 argc == 3 ? argv[2] : "");
956 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
957 printf("Too long VENDOR command.\n");
960 return wpa_ctrl_command(ctrl, cmd);
964 struct hostapd_cli_cmd {
966 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
969 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
970 { "ping", hostapd_cli_cmd_ping },
971 { "mib", hostapd_cli_cmd_mib },
972 { "relog", hostapd_cli_cmd_relog },
973 { "status", hostapd_cli_cmd_status },
974 { "sta", hostapd_cli_cmd_sta },
975 { "all_sta", hostapd_cli_cmd_all_sta },
976 { "new_sta", hostapd_cli_cmd_new_sta },
977 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
978 { "disassociate", hostapd_cli_cmd_disassociate },
979 #ifdef CONFIG_IEEE80211W
980 { "sa_query", hostapd_cli_cmd_sa_query },
981 #endif /* CONFIG_IEEE80211W */
983 { "wps_pin", hostapd_cli_cmd_wps_pin },
984 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
985 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
986 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
987 #ifdef CONFIG_WPS_NFC
988 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
989 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
990 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
991 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
992 #endif /* CONFIG_WPS_NFC */
993 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
994 { "wps_config", hostapd_cli_cmd_wps_config },
995 { "wps_get_status", hostapd_cli_cmd_wps_get_status },
996 #endif /* CONFIG_WPS */
997 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
998 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
999 { "get_config", hostapd_cli_cmd_get_config },
1000 { "help", hostapd_cli_cmd_help },
1001 { "interface", hostapd_cli_cmd_interface },
1002 { "level", hostapd_cli_cmd_level },
1003 { "license", hostapd_cli_cmd_license },
1004 { "quit", hostapd_cli_cmd_quit },
1005 { "set", hostapd_cli_cmd_set },
1006 { "get", hostapd_cli_cmd_get },
1007 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
1008 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
1009 { "chan_switch", hostapd_cli_cmd_chan_switch },
1010 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
1011 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
1012 { "vendor", hostapd_cli_cmd_vendor },
1017 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1019 struct hostapd_cli_cmd *cmd, *match = NULL;
1023 cmd = hostapd_cli_commands;
1025 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1027 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1028 /* we have an exact match */
1038 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1039 cmd = hostapd_cli_commands;
1041 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1043 printf(" %s", cmd->cmd);
1048 } else if (count == 0) {
1049 printf("Unknown command '%s'\n", argv[0]);
1051 match->handler(ctrl, argc - 1, &argv[1]);
1056 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1060 if (ctrl_conn == NULL)
1062 while (wpa_ctrl_pending(ctrl)) {
1064 size_t len = sizeof(buf) - 1;
1065 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1068 hostapd_cli_action_process(buf, len);
1070 if (in_read && first)
1073 printf("%s\n", buf);
1076 printf("Could not read pending message.\n");
1085 static int tokenize_cmd(char *cmd, char *argv[])
1098 if (argc == max_args)
1101 char *pos2 = os_strrchr(pos, '"');
1105 while (*pos != '\0' && *pos != ' ')
1115 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1117 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1118 printf("Connection to hostapd lost - trying to reconnect\n");
1119 hostapd_cli_close_connection();
1122 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1124 printf("Connection to hostapd re-established\n");
1125 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1126 hostapd_cli_attached = 1;
1128 printf("Warning: Failed to attach to "
1134 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1135 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1139 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1145 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1147 char *argv[max_args];
1149 argc = tokenize_cmd(cmd, argv);
1151 wpa_request(ctrl_conn, argc, argv);
1155 static void hostapd_cli_edit_eof_cb(void *ctx)
1161 static void hostapd_cli_interactive(void)
1163 printf("\nInteractive mode\n\n");
1165 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1166 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1167 NULL, NULL, NULL, NULL);
1168 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1172 edit_deinit(NULL, NULL);
1173 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1177 static void hostapd_cli_cleanup(void)
1179 hostapd_cli_close_connection();
1181 os_daemonize_terminate(pid_file);
1183 os_program_deinit();
1187 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1195 fd = wpa_ctrl_get_fd(ctrl);
1197 while (!hostapd_cli_quit) {
1200 tv.tv_sec = ping_interval;
1202 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1203 if (res < 0 && errno != EINTR) {
1208 if (FD_ISSET(fd, &rfds))
1209 hostapd_cli_recv_pending(ctrl, 0, 1);
1211 len = sizeof(buf) - 1;
1212 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1213 hostapd_cli_action_process) < 0 ||
1214 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1215 printf("hostapd did not reply to PING "
1216 "command - exiting\n");
1224 int main(int argc, char *argv[])
1226 int warning_displayed = 0;
1230 if (os_program_init())
1234 c = getopt(argc, argv, "a:BhG:i:p:v");
1239 action_file = optarg;
1245 ping_interval = atoi(optarg);
1251 printf("%s\n", hostapd_cli_version);
1254 os_free(ctrl_ifname);
1255 ctrl_ifname = os_strdup(optarg);
1258 ctrl_iface_dir = optarg;
1266 interactive = (argc == optind) && (action_file == NULL);
1269 printf("%s\n\n%s\n\n", hostapd_cli_version,
1270 hostapd_cli_license);
1277 if (ctrl_ifname == NULL) {
1278 struct dirent *dent;
1279 DIR *dir = opendir(ctrl_iface_dir);
1281 while ((dent = readdir(dir))) {
1282 if (os_strcmp(dent->d_name, ".") == 0
1284 os_strcmp(dent->d_name, "..") == 0)
1286 printf("Selected interface '%s'\n",
1288 ctrl_ifname = os_strdup(dent->d_name);
1294 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1296 if (warning_displayed)
1297 printf("Connection established.\n");
1302 perror("Failed to connect to hostapd - "
1307 if (!warning_displayed) {
1308 printf("Could not connect to hostapd - re-trying\n");
1309 warning_displayed = 1;
1315 if (interactive || action_file) {
1316 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1317 hostapd_cli_attached = 1;
1319 printf("Warning: Failed to attach to hostapd.\n");
1325 if (daemonize && os_daemonize(pid_file))
1329 hostapd_cli_interactive();
1330 else if (action_file)
1331 hostapd_cli_action(ctrl_conn);
1333 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1335 os_free(ctrl_ifname);
1337 hostapd_cli_cleanup();