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 struct hostapd_cli_cmd {
851 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
854 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
855 { "ping", hostapd_cli_cmd_ping },
856 { "mib", hostapd_cli_cmd_mib },
857 { "relog", hostapd_cli_cmd_relog },
858 { "status", hostapd_cli_cmd_status },
859 { "sta", hostapd_cli_cmd_sta },
860 { "all_sta", hostapd_cli_cmd_all_sta },
861 { "new_sta", hostapd_cli_cmd_new_sta },
862 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
863 { "disassociate", hostapd_cli_cmd_disassociate },
864 #ifdef CONFIG_IEEE80211W
865 { "sa_query", hostapd_cli_cmd_sa_query },
866 #endif /* CONFIG_IEEE80211W */
868 { "wps_pin", hostapd_cli_cmd_wps_pin },
869 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
870 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
871 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
872 #ifdef CONFIG_WPS_NFC
873 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
874 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
875 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
876 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
877 #endif /* CONFIG_WPS_NFC */
878 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
879 { "wps_config", hostapd_cli_cmd_wps_config },
880 { "wps_get_status", hostapd_cli_cmd_wps_get_status },
881 #endif /* CONFIG_WPS */
882 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
883 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
884 { "get_config", hostapd_cli_cmd_get_config },
885 { "help", hostapd_cli_cmd_help },
886 { "interface", hostapd_cli_cmd_interface },
887 { "level", hostapd_cli_cmd_level },
888 { "license", hostapd_cli_cmd_license },
889 { "quit", hostapd_cli_cmd_quit },
890 { "set", hostapd_cli_cmd_set },
891 { "get", hostapd_cli_cmd_get },
892 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
893 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
898 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
900 struct hostapd_cli_cmd *cmd, *match = NULL;
904 cmd = hostapd_cli_commands;
906 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
908 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
909 /* we have an exact match */
919 printf("Ambiguous command '%s'; possible commands:", argv[0]);
920 cmd = hostapd_cli_commands;
922 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
924 printf(" %s", cmd->cmd);
929 } else if (count == 0) {
930 printf("Unknown command '%s'\n", argv[0]);
932 match->handler(ctrl, argc - 1, &argv[1]);
937 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
941 if (ctrl_conn == NULL)
943 while (wpa_ctrl_pending(ctrl)) {
945 size_t len = sizeof(buf) - 1;
946 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
949 hostapd_cli_action_process(buf, len);
951 if (in_read && first)
957 printf("Could not read pending message.\n");
966 static int tokenize_cmd(char *cmd, char *argv[])
979 if (argc == max_args)
982 char *pos2 = os_strrchr(pos, '"');
986 while (*pos != '\0' && *pos != ' ')
996 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
998 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
999 printf("Connection to hostapd lost - trying to reconnect\n");
1000 hostapd_cli_close_connection();
1003 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1005 printf("Connection to hostapd re-established\n");
1006 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1007 hostapd_cli_attached = 1;
1009 printf("Warning: Failed to attach to "
1015 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1016 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1020 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1026 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1028 char *argv[max_args];
1030 argc = tokenize_cmd(cmd, argv);
1032 wpa_request(ctrl_conn, argc, argv);
1036 static void hostapd_cli_edit_eof_cb(void *ctx)
1042 static void hostapd_cli_interactive(void)
1044 printf("\nInteractive mode\n\n");
1046 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1047 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1048 NULL, NULL, NULL, NULL);
1049 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1053 edit_deinit(NULL, NULL);
1054 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1058 static void hostapd_cli_cleanup(void)
1060 hostapd_cli_close_connection();
1062 os_daemonize_terminate(pid_file);
1064 os_program_deinit();
1068 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1076 fd = wpa_ctrl_get_fd(ctrl);
1078 while (!hostapd_cli_quit) {
1081 tv.tv_sec = ping_interval;
1083 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1084 if (res < 0 && errno != EINTR) {
1089 if (FD_ISSET(fd, &rfds))
1090 hostapd_cli_recv_pending(ctrl, 0, 1);
1092 len = sizeof(buf) - 1;
1093 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1094 hostapd_cli_action_process) < 0 ||
1095 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1096 printf("hostapd did not reply to PING "
1097 "command - exiting\n");
1105 int main(int argc, char *argv[])
1107 int warning_displayed = 0;
1111 if (os_program_init())
1115 c = getopt(argc, argv, "a:BhG:i:p:v");
1120 action_file = optarg;
1126 ping_interval = atoi(optarg);
1132 printf("%s\n", hostapd_cli_version);
1135 os_free(ctrl_ifname);
1136 ctrl_ifname = os_strdup(optarg);
1139 ctrl_iface_dir = optarg;
1147 interactive = (argc == optind) && (action_file == NULL);
1150 printf("%s\n\n%s\n\n", hostapd_cli_version,
1151 hostapd_cli_license);
1158 if (ctrl_ifname == NULL) {
1159 struct dirent *dent;
1160 DIR *dir = opendir(ctrl_iface_dir);
1162 while ((dent = readdir(dir))) {
1163 if (os_strcmp(dent->d_name, ".") == 0
1165 os_strcmp(dent->d_name, "..") == 0)
1167 printf("Selected interface '%s'\n",
1169 ctrl_ifname = os_strdup(dent->d_name);
1175 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1177 if (warning_displayed)
1178 printf("Connection established.\n");
1183 perror("Failed to connect to hostapd - "
1188 if (!warning_displayed) {
1189 printf("Could not connect to hostapd - re-trying\n");
1190 warning_displayed = 1;
1196 if (interactive || action_file) {
1197 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1198 hostapd_cli_attached = 1;
1200 printf("Warning: Failed to attach to hostapd.\n");
1206 if (daemonize && os_daemonize(pid_file))
1210 hostapd_cli_interactive();
1211 else if (action_file)
1212 hostapd_cli_action(ctrl_conn);
1214 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1216 os_free(ctrl_ifname);
1218 hostapd_cli_cleanup();