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_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
748 hostapd_cli_quit = 1;
755 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
759 printf("Invalid LEVEL command: needs one argument (debug "
763 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
764 return wpa_ctrl_command(ctrl, cmd);
768 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
773 dir = opendir(ctrl_iface_dir);
775 printf("Control interface directory '%s' could not be "
776 "openned.\n", ctrl_iface_dir);
780 printf("Available interfaces:\n");
781 while ((dent = readdir(dir))) {
782 if (strcmp(dent->d_name, ".") == 0 ||
783 strcmp(dent->d_name, "..") == 0)
785 printf("%s\n", dent->d_name);
791 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
795 hostapd_cli_list_interfaces(ctrl);
799 hostapd_cli_close_connection();
801 ctrl_ifname = strdup(argv[0]);
803 if (hostapd_cli_open_connection(ctrl_ifname)) {
804 printf("Connected to interface '%s.\n", ctrl_ifname);
805 if (wpa_ctrl_attach(ctrl_conn) == 0) {
806 hostapd_cli_attached = 1;
808 printf("Warning: Failed to attach to "
812 printf("Could not connect to interface '%s' - re-trying\n",
819 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
825 printf("Invalid SET command: needs two arguments (variable "
826 "name and value)\n");
830 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
831 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
832 printf("Too long SET command.\n");
835 return wpa_ctrl_command(ctrl, cmd);
839 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
845 printf("Invalid GET command: needs one argument (variable "
850 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
851 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
852 printf("Too long GET command.\n");
855 return wpa_ctrl_command(ctrl, cmd);
859 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
860 int argc, char *argv[])
869 printf("Invalid chan_switch command: needs at least two "
870 "arguments (count and freq)\n"
871 "usage: <cs_count> <freq> [sec_channel_offset=] "
872 "[center_freq1=] [center_freq2=] [bandwidth=] "
873 "[blocktx] [ht|vht]\n");
877 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
879 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
880 printf("Too long CHAN_SWITCH command.\n");
885 for (i = 2; i < argc; i++) {
887 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
888 if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) {
889 printf("Too long CHAN_SWITCH command.\n");
894 return wpa_ctrl_command(ctrl, cmd);
898 struct hostapd_cli_cmd {
900 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
903 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
904 { "ping", hostapd_cli_cmd_ping },
905 { "mib", hostapd_cli_cmd_mib },
906 { "relog", hostapd_cli_cmd_relog },
907 { "status", hostapd_cli_cmd_status },
908 { "sta", hostapd_cli_cmd_sta },
909 { "all_sta", hostapd_cli_cmd_all_sta },
910 { "new_sta", hostapd_cli_cmd_new_sta },
911 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
912 { "disassociate", hostapd_cli_cmd_disassociate },
913 #ifdef CONFIG_IEEE80211W
914 { "sa_query", hostapd_cli_cmd_sa_query },
915 #endif /* CONFIG_IEEE80211W */
917 { "wps_pin", hostapd_cli_cmd_wps_pin },
918 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
919 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
920 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
921 #ifdef CONFIG_WPS_NFC
922 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
923 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
924 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
925 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
926 #endif /* CONFIG_WPS_NFC */
927 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
928 { "wps_config", hostapd_cli_cmd_wps_config },
929 { "wps_get_status", hostapd_cli_cmd_wps_get_status },
930 #endif /* CONFIG_WPS */
931 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
932 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
933 { "get_config", hostapd_cli_cmd_get_config },
934 { "help", hostapd_cli_cmd_help },
935 { "interface", hostapd_cli_cmd_interface },
936 { "level", hostapd_cli_cmd_level },
937 { "license", hostapd_cli_cmd_license },
938 { "quit", hostapd_cli_cmd_quit },
939 { "set", hostapd_cli_cmd_set },
940 { "get", hostapd_cli_cmd_get },
941 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
942 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
943 { "chan_switch", hostapd_cli_cmd_chan_switch },
948 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
950 struct hostapd_cli_cmd *cmd, *match = NULL;
954 cmd = hostapd_cli_commands;
956 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
958 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
959 /* we have an exact match */
969 printf("Ambiguous command '%s'; possible commands:", argv[0]);
970 cmd = hostapd_cli_commands;
972 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
974 printf(" %s", cmd->cmd);
979 } else if (count == 0) {
980 printf("Unknown command '%s'\n", argv[0]);
982 match->handler(ctrl, argc - 1, &argv[1]);
987 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
991 if (ctrl_conn == NULL)
993 while (wpa_ctrl_pending(ctrl)) {
995 size_t len = sizeof(buf) - 1;
996 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
999 hostapd_cli_action_process(buf, len);
1001 if (in_read && first)
1004 printf("%s\n", buf);
1007 printf("Could not read pending message.\n");
1016 static int tokenize_cmd(char *cmd, char *argv[])
1029 if (argc == max_args)
1032 char *pos2 = os_strrchr(pos, '"');
1036 while (*pos != '\0' && *pos != ' ')
1046 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1048 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1049 printf("Connection to hostapd lost - trying to reconnect\n");
1050 hostapd_cli_close_connection();
1053 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1055 printf("Connection to hostapd re-established\n");
1056 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1057 hostapd_cli_attached = 1;
1059 printf("Warning: Failed to attach to "
1065 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1066 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1070 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1076 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1078 char *argv[max_args];
1080 argc = tokenize_cmd(cmd, argv);
1082 wpa_request(ctrl_conn, argc, argv);
1086 static void hostapd_cli_edit_eof_cb(void *ctx)
1092 static void hostapd_cli_interactive(void)
1094 printf("\nInteractive mode\n\n");
1096 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1097 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1098 NULL, NULL, NULL, NULL);
1099 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1103 edit_deinit(NULL, NULL);
1104 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1108 static void hostapd_cli_cleanup(void)
1110 hostapd_cli_close_connection();
1112 os_daemonize_terminate(pid_file);
1114 os_program_deinit();
1118 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1126 fd = wpa_ctrl_get_fd(ctrl);
1128 while (!hostapd_cli_quit) {
1131 tv.tv_sec = ping_interval;
1133 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1134 if (res < 0 && errno != EINTR) {
1139 if (FD_ISSET(fd, &rfds))
1140 hostapd_cli_recv_pending(ctrl, 0, 1);
1142 len = sizeof(buf) - 1;
1143 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1144 hostapd_cli_action_process) < 0 ||
1145 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1146 printf("hostapd did not reply to PING "
1147 "command - exiting\n");
1155 int main(int argc, char *argv[])
1157 int warning_displayed = 0;
1161 if (os_program_init())
1165 c = getopt(argc, argv, "a:BhG:i:p:v");
1170 action_file = optarg;
1176 ping_interval = atoi(optarg);
1182 printf("%s\n", hostapd_cli_version);
1185 os_free(ctrl_ifname);
1186 ctrl_ifname = os_strdup(optarg);
1189 ctrl_iface_dir = optarg;
1197 interactive = (argc == optind) && (action_file == NULL);
1200 printf("%s\n\n%s\n\n", hostapd_cli_version,
1201 hostapd_cli_license);
1208 if (ctrl_ifname == NULL) {
1209 struct dirent *dent;
1210 DIR *dir = opendir(ctrl_iface_dir);
1212 while ((dent = readdir(dir))) {
1213 if (os_strcmp(dent->d_name, ".") == 0
1215 os_strcmp(dent->d_name, "..") == 0)
1217 printf("Selected interface '%s'\n",
1219 ctrl_ifname = os_strdup(dent->d_name);
1225 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1227 if (warning_displayed)
1228 printf("Connection established.\n");
1233 perror("Failed to connect to hostapd - "
1238 if (!warning_displayed) {
1239 printf("Could not connect to hostapd - re-trying\n");
1240 warning_displayed = 1;
1246 if (interactive || action_file) {
1247 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1248 hostapd_cli_attached = 1;
1250 printf("Warning: Failed to attach to hostapd.\n");
1256 if (daemonize && os_daemonize(pid_file))
1260 hostapd_cli_interactive();
1261 else if (action_file)
1262 hostapd_cli_action(ctrl_conn);
1264 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1266 os_free(ctrl_ifname);
1268 hostapd_cli_cleanup();