2 * hostapd - command line interface for hostapd daemon
3 * Copyright (c) 2004-2013, 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-2013, 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 return wpa_ctrl_command(ctrl, "STATUS");
225 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
227 return wpa_ctrl_command(ctrl, "MIB");
231 static int hostapd_cli_exec(const char *program, const char *arg1,
239 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
240 cmd = os_malloc(len);
243 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
244 if (res < 0 || (size_t) res >= len) {
252 #endif /* _WIN32_WCE */
259 static void hostapd_cli_action_process(char *msg, size_t len)
265 pos = os_strchr(pos, '>');
272 hostapd_cli_exec(action_file, ctrl_ifname, pos);
276 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
280 printf("Invalid 'sta' command - exactly one argument, STA "
281 "address, is required.\n");
284 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
285 return wpa_ctrl_command(ctrl, buf);
289 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
294 printf("Invalid 'new_sta' command - exactly one argument, STA "
295 "address, is required.\n");
298 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
299 return wpa_ctrl_command(ctrl, buf);
303 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
308 printf("Invalid 'deauthenticate' command - exactly one "
309 "argument, STA address, is required.\n");
313 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
316 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
317 return wpa_ctrl_command(ctrl, buf);
321 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
326 printf("Invalid 'disassociate' command - exactly one "
327 "argument, STA address, is required.\n");
331 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
334 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
335 return wpa_ctrl_command(ctrl, buf);
339 #ifdef CONFIG_IEEE80211W
340 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
345 printf("Invalid 'sa_query' command - exactly one argument, "
346 "STA address, is required.\n");
349 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
350 return wpa_ctrl_command(ctrl, buf);
352 #endif /* CONFIG_IEEE80211W */
356 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
361 printf("Invalid 'wps_pin' command - at least two arguments, "
362 "UUID and PIN, are required.\n");
366 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
367 argv[0], argv[1], argv[2], argv[3]);
369 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
370 argv[0], argv[1], argv[2]);
372 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
373 return wpa_ctrl_command(ctrl, buf);
377 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
383 if (argc != 1 && argc != 2) {
384 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
385 "- PIN to be verified\n");
390 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
393 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
395 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
396 printf("Too long WPS_CHECK_PIN command.\n");
399 return wpa_ctrl_command(ctrl, cmd);
403 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
406 return wpa_ctrl_command(ctrl, "WPS_PBC");
410 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
413 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
417 #ifdef CONFIG_WPS_NFC
418 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
426 printf("Invalid 'wps_nfc_tag_read' command - one argument "
431 buflen = 18 + os_strlen(argv[0]);
432 buf = os_malloc(buflen);
435 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
437 ret = wpa_ctrl_command(ctrl, buf);
444 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
445 int argc, char *argv[])
451 printf("Invalid 'wps_nfc_config_token' command - one argument "
456 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
458 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
459 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
462 return wpa_ctrl_command(ctrl, cmd);
466 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
467 int argc, char *argv[])
473 printf("Invalid 'wps_nfc_token' command - one argument is "
478 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
479 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
480 printf("Too long WPS_NFC_TOKEN command.\n");
483 return wpa_ctrl_command(ctrl, cmd);
487 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
488 int argc, char *argv[])
494 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
499 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
501 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
502 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
505 return wpa_ctrl_command(ctrl, cmd);
508 #endif /* CONFIG_WPS_NFC */
511 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
516 printf("Invalid 'wps_ap_pin' command - at least one argument "
521 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
522 argv[0], argv[1], argv[2]);
524 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
527 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
528 return wpa_ctrl_command(ctrl, buf);
532 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
535 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
539 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
543 char ssid_hex[2 * 32 + 1];
544 char key_hex[2 * 64 + 1];
548 printf("Invalid 'wps_config' command - at least two arguments "
554 for (i = 0; i < 32; i++) {
555 if (argv[0][i] == '\0')
557 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
562 for (i = 0; i < 64; i++) {
563 if (argv[3][i] == '\0')
565 os_snprintf(&key_hex[i * 2], 3, "%02x",
571 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
572 ssid_hex, argv[1], argv[2], key_hex);
574 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
575 ssid_hex, argv[1], argv[2]);
577 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
579 return wpa_ctrl_command(ctrl, buf);
581 #endif /* CONFIG_WPS */
584 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
591 printf("Invalid 'disassoc_imminent' command - two arguments "
592 "(STA addr and Disassociation Timer) are needed\n");
596 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
598 if (res < 0 || res >= (int) sizeof(buf))
600 return wpa_ctrl_command(ctrl, buf);
604 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
611 printf("Invalid 'ess_disassoc' command - three arguments (STA "
612 "addr, disassoc timer, and URL) are needed\n");
616 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
617 argv[0], argv[1], argv[2]);
618 if (res < 0 || res >= (int) sizeof(buf))
620 return wpa_ctrl_command(ctrl, buf);
624 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
627 return wpa_ctrl_command(ctrl, "GET_CONFIG");
631 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
632 char *addr, size_t addr_len)
634 char buf[4096], *pos;
638 if (ctrl_conn == NULL) {
639 printf("Not connected to hostapd - command dropped.\n");
642 len = sizeof(buf) - 1;
643 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
646 printf("'%s' command timed out.\n", cmd);
648 } else if (ret < 0) {
649 printf("'%s' command failed.\n", cmd);
654 if (memcmp(buf, "FAIL", 4) == 0)
659 while (*pos != '\0' && *pos != '\n')
662 os_strlcpy(addr, buf, addr_len);
667 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
670 char addr[32], cmd[64];
672 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
675 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
676 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
682 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
684 printf("%s", commands_help);
689 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
692 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
697 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
698 int argc, char *argv[])
704 printf("Invalid 'set_qos_map_set' command - "
705 "one argument (comma delimited QoS map set) "
710 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
711 if (res < 0 || res >= (int) sizeof(buf))
713 return wpa_ctrl_command(ctrl, buf);
717 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
718 int argc, char *argv[])
724 printf("Invalid 'send_qos_map_conf' command - "
725 "one argument (STA addr) is needed\n");
729 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
730 if (res < 0 || res >= (int) sizeof(buf))
732 return wpa_ctrl_command(ctrl, buf);
736 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
738 hostapd_cli_quit = 1;
745 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
749 printf("Invalid LEVEL command: needs one argument (debug "
753 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
754 return wpa_ctrl_command(ctrl, cmd);
758 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
763 dir = opendir(ctrl_iface_dir);
765 printf("Control interface directory '%s' could not be "
766 "openned.\n", ctrl_iface_dir);
770 printf("Available interfaces:\n");
771 while ((dent = readdir(dir))) {
772 if (strcmp(dent->d_name, ".") == 0 ||
773 strcmp(dent->d_name, "..") == 0)
775 printf("%s\n", dent->d_name);
781 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
785 hostapd_cli_list_interfaces(ctrl);
789 hostapd_cli_close_connection();
791 ctrl_ifname = strdup(argv[0]);
793 if (hostapd_cli_open_connection(ctrl_ifname)) {
794 printf("Connected to interface '%s.\n", ctrl_ifname);
795 if (wpa_ctrl_attach(ctrl_conn) == 0) {
796 hostapd_cli_attached = 1;
798 printf("Warning: Failed to attach to "
802 printf("Could not connect to interface '%s' - re-trying\n",
809 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
815 printf("Invalid SET command: needs two arguments (variable "
816 "name and value)\n");
820 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
821 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
822 printf("Too long SET command.\n");
825 return wpa_ctrl_command(ctrl, cmd);
829 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
835 printf("Invalid GET command: needs one argument (variable "
840 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
841 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
842 printf("Too long GET command.\n");
845 return wpa_ctrl_command(ctrl, cmd);
849 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
850 int argc, char *argv[])
859 printf("Invalid chan_switch command: needs at least two "
860 "arguments (count and freq)\n"
861 "usage: <cs_count> <freq> [sec_channel_offset=] "
862 "[center_freq1=] [center_freq2=] [bandwidth=] "
863 "[blocktx] [ht|vht]\n");
867 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
869 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
870 printf("Too long CHAN_SWITCH command.\n");
875 for (i = 2; i < argc; i++) {
877 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
878 if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) {
879 printf("Too long CHAN_SWITCH command.\n");
884 return wpa_ctrl_command(ctrl, cmd);
888 struct hostapd_cli_cmd {
890 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
893 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
894 { "ping", hostapd_cli_cmd_ping },
895 { "mib", hostapd_cli_cmd_mib },
896 { "relog", hostapd_cli_cmd_relog },
897 { "status", hostapd_cli_cmd_status },
898 { "sta", hostapd_cli_cmd_sta },
899 { "all_sta", hostapd_cli_cmd_all_sta },
900 { "new_sta", hostapd_cli_cmd_new_sta },
901 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
902 { "disassociate", hostapd_cli_cmd_disassociate },
903 #ifdef CONFIG_IEEE80211W
904 { "sa_query", hostapd_cli_cmd_sa_query },
905 #endif /* CONFIG_IEEE80211W */
907 { "wps_pin", hostapd_cli_cmd_wps_pin },
908 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
909 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
910 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
911 #ifdef CONFIG_WPS_NFC
912 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
913 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
914 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
915 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
916 #endif /* CONFIG_WPS_NFC */
917 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
918 { "wps_config", hostapd_cli_cmd_wps_config },
919 { "wps_get_status", hostapd_cli_cmd_wps_get_status },
920 #endif /* CONFIG_WPS */
921 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
922 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
923 { "get_config", hostapd_cli_cmd_get_config },
924 { "help", hostapd_cli_cmd_help },
925 { "interface", hostapd_cli_cmd_interface },
926 { "level", hostapd_cli_cmd_level },
927 { "license", hostapd_cli_cmd_license },
928 { "quit", hostapd_cli_cmd_quit },
929 { "set", hostapd_cli_cmd_set },
930 { "get", hostapd_cli_cmd_get },
931 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
932 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
933 { "chan_switch", hostapd_cli_cmd_chan_switch },
938 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
940 struct hostapd_cli_cmd *cmd, *match = NULL;
944 cmd = hostapd_cli_commands;
946 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
948 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
949 /* we have an exact match */
959 printf("Ambiguous command '%s'; possible commands:", argv[0]);
960 cmd = hostapd_cli_commands;
962 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
964 printf(" %s", cmd->cmd);
969 } else if (count == 0) {
970 printf("Unknown command '%s'\n", argv[0]);
972 match->handler(ctrl, argc - 1, &argv[1]);
977 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
981 if (ctrl_conn == NULL)
983 while (wpa_ctrl_pending(ctrl)) {
985 size_t len = sizeof(buf) - 1;
986 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
989 hostapd_cli_action_process(buf, len);
991 if (in_read && first)
997 printf("Could not read pending message.\n");
1006 static int tokenize_cmd(char *cmd, char *argv[])
1019 if (argc == max_args)
1022 char *pos2 = os_strrchr(pos, '"');
1026 while (*pos != '\0' && *pos != ' ')
1036 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1038 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1039 printf("Connection to hostapd lost - trying to reconnect\n");
1040 hostapd_cli_close_connection();
1043 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1045 printf("Connection to hostapd re-established\n");
1046 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1047 hostapd_cli_attached = 1;
1049 printf("Warning: Failed to attach to "
1055 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1056 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1060 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1066 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1068 char *argv[max_args];
1070 argc = tokenize_cmd(cmd, argv);
1072 wpa_request(ctrl_conn, argc, argv);
1076 static void hostapd_cli_edit_eof_cb(void *ctx)
1082 static void hostapd_cli_interactive(void)
1084 printf("\nInteractive mode\n\n");
1086 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1087 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1088 NULL, NULL, NULL, NULL);
1089 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1093 edit_deinit(NULL, NULL);
1094 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1098 static void hostapd_cli_cleanup(void)
1100 hostapd_cli_close_connection();
1102 os_daemonize_terminate(pid_file);
1104 os_program_deinit();
1108 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1116 fd = wpa_ctrl_get_fd(ctrl);
1118 while (!hostapd_cli_quit) {
1121 tv.tv_sec = ping_interval;
1123 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1124 if (res < 0 && errno != EINTR) {
1129 if (FD_ISSET(fd, &rfds))
1130 hostapd_cli_recv_pending(ctrl, 0, 1);
1132 len = sizeof(buf) - 1;
1133 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1134 hostapd_cli_action_process) < 0 ||
1135 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1136 printf("hostapd did not reply to PING "
1137 "command - exiting\n");
1145 int main(int argc, char *argv[])
1147 int warning_displayed = 0;
1151 if (os_program_init())
1155 c = getopt(argc, argv, "a:BhG:i:p:v");
1160 action_file = optarg;
1166 ping_interval = atoi(optarg);
1172 printf("%s\n", hostapd_cli_version);
1175 os_free(ctrl_ifname);
1176 ctrl_ifname = os_strdup(optarg);
1179 ctrl_iface_dir = optarg;
1187 interactive = (argc == optind) && (action_file == NULL);
1190 printf("%s\n\n%s\n\n", hostapd_cli_version,
1191 hostapd_cli_license);
1198 if (ctrl_ifname == NULL) {
1199 struct dirent *dent;
1200 DIR *dir = opendir(ctrl_iface_dir);
1202 while ((dent = readdir(dir))) {
1203 if (os_strcmp(dent->d_name, ".") == 0
1205 os_strcmp(dent->d_name, "..") == 0)
1207 printf("Selected interface '%s'\n",
1209 ctrl_ifname = os_strdup(dent->d_name);
1215 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1217 if (warning_displayed)
1218 printf("Connection established.\n");
1223 perror("Failed to connect to hostapd - "
1228 if (!warning_displayed) {
1229 printf("Could not connect to hostapd - re-trying\n");
1230 warning_displayed = 1;
1236 if (interactive || action_file) {
1237 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1238 hostapd_cli_attached = 1;
1240 printf("Warning: Failed to attach to hostapd.\n");
1246 if (daemonize && os_daemonize(pid_file))
1250 hostapd_cli_interactive();
1251 else if (action_file)
1252 hostapd_cli_action(ctrl_conn);
1254 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1256 os_free(ctrl_ifname);
1258 hostapd_cli_cleanup();