2 * hostapd - command line interface for hostapd daemon
3 * Copyright (c) 2004-2012, 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 #endif /* CONFIG_WPS */
83 " get_config show current configuration\n"
84 " help show this usage help\n"
85 " interface [ifname] show interfaces/select interface\n"
86 " level <debug level> change debug level\n"
87 " license show full hostapd_cli license\n"
88 " quit exit hostapd_cli\n";
90 static struct wpa_ctrl *ctrl_conn;
91 static int hostapd_cli_quit = 0;
92 static int hostapd_cli_attached = 0;
94 #ifndef CONFIG_CTRL_IFACE_DIR
95 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
96 #endif /* CONFIG_CTRL_IFACE_DIR */
97 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
99 static char *ctrl_ifname = NULL;
100 static const char *pid_file = NULL;
101 static const char *action_file = NULL;
102 static int ping_interval = 5;
103 static int interactive = 0;
106 static void usage(void)
108 fprintf(stderr, "%s\n", hostapd_cli_version);
111 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
113 " [-G<ping interval>] [command..]\n"
116 " -h help (show this usage text)\n"
117 " -v shown version information\n"
118 " -p<path> path to find control sockets (default: "
119 "/var/run/hostapd)\n"
120 " -a<file> run in daemon mode executing the action file "
123 " -B run a daemon in the background\n"
124 " -i<ifname> Interface to listen on (default: first "
125 "interface found in the\n"
132 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
140 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
141 cfile = malloc(flen);
144 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
146 ctrl_conn = wpa_ctrl_open(cfile);
152 static void hostapd_cli_close_connection(void)
154 if (ctrl_conn == NULL)
157 if (hostapd_cli_attached) {
158 wpa_ctrl_detach(ctrl_conn);
159 hostapd_cli_attached = 0;
161 wpa_ctrl_close(ctrl_conn);
166 static void hostapd_cli_msg_cb(char *msg, size_t len)
172 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
178 if (ctrl_conn == NULL) {
179 printf("Not connected to hostapd - command dropped.\n");
182 len = sizeof(buf) - 1;
183 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
186 printf("'%s' command timed out.\n", cmd);
188 } else if (ret < 0) {
189 printf("'%s' command failed.\n", cmd);
200 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
202 return _wpa_ctrl_command(ctrl, cmd, 1);
206 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
208 return wpa_ctrl_command(ctrl, "PING");
212 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
214 return wpa_ctrl_command(ctrl, "RELOG");
218 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
220 return wpa_ctrl_command(ctrl, "MIB");
224 static int hostapd_cli_exec(const char *program, const char *arg1,
232 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
233 cmd = os_malloc(len);
236 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
237 if (res < 0 || (size_t) res >= len) {
245 #endif /* _WIN32_WCE */
252 static void hostapd_cli_action_process(char *msg, size_t len)
258 pos = os_strchr(pos, '>');
265 hostapd_cli_exec(action_file, ctrl_ifname, pos);
269 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
273 printf("Invalid 'sta' command - exactly one argument, STA "
274 "address, is required.\n");
277 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
278 return wpa_ctrl_command(ctrl, buf);
282 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
287 printf("Invalid 'new_sta' command - exactly one argument, STA "
288 "address, is required.\n");
291 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
292 return wpa_ctrl_command(ctrl, buf);
296 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
301 printf("Invalid 'deauthenticate' command - exactly one "
302 "argument, STA address, is required.\n");
306 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
309 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
310 return wpa_ctrl_command(ctrl, buf);
314 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
319 printf("Invalid 'disassociate' command - exactly one "
320 "argument, STA address, is required.\n");
324 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
327 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
328 return wpa_ctrl_command(ctrl, buf);
332 #ifdef CONFIG_IEEE80211W
333 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
338 printf("Invalid 'sa_query' command - exactly one argument, "
339 "STA address, is required.\n");
342 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
343 return wpa_ctrl_command(ctrl, buf);
345 #endif /* CONFIG_IEEE80211W */
349 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
354 printf("Invalid 'wps_pin' command - at least two arguments, "
355 "UUID and PIN, are required.\n");
359 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
360 argv[0], argv[1], argv[2], argv[3]);
362 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
363 argv[0], argv[1], argv[2]);
365 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
366 return wpa_ctrl_command(ctrl, buf);
370 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
376 if (argc != 1 && argc != 2) {
377 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
378 "- PIN to be verified\n");
383 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
386 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
388 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
389 printf("Too long WPS_CHECK_PIN command.\n");
392 return wpa_ctrl_command(ctrl, cmd);
396 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
399 return wpa_ctrl_command(ctrl, "WPS_PBC");
403 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
406 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
410 #ifdef CONFIG_WPS_NFC
411 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
419 printf("Invalid 'wps_nfc_tag_read' command - one argument "
424 buflen = 18 + os_strlen(argv[0]);
425 buf = os_malloc(buflen);
428 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
430 ret = wpa_ctrl_command(ctrl, buf);
437 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
438 int argc, char *argv[])
444 printf("Invalid 'wps_nfc_config_token' command - one argument "
449 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
451 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
452 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
455 return wpa_ctrl_command(ctrl, cmd);
459 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
460 int argc, char *argv[])
466 printf("Invalid 'wps_nfc_token' command - one argument is "
471 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
472 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
473 printf("Too long WPS_NFC_TOKEN command.\n");
476 return wpa_ctrl_command(ctrl, cmd);
480 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
481 int argc, char *argv[])
487 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
492 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
494 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
495 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
498 return wpa_ctrl_command(ctrl, cmd);
501 #endif /* CONFIG_WPS_NFC */
504 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
509 printf("Invalid 'wps_ap_pin' command - at least one argument "
514 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
515 argv[0], argv[1], argv[2]);
517 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
520 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
521 return wpa_ctrl_command(ctrl, buf);
525 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
529 char ssid_hex[2 * 32 + 1];
530 char key_hex[2 * 64 + 1];
534 printf("Invalid 'wps_config' command - at least two arguments "
540 for (i = 0; i < 32; i++) {
541 if (argv[0][i] == '\0')
543 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
548 for (i = 0; i < 64; i++) {
549 if (argv[3][i] == '\0')
551 os_snprintf(&key_hex[i * 2], 3, "%02x",
557 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
558 ssid_hex, argv[1], argv[2], key_hex);
560 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
561 ssid_hex, argv[1], argv[2]);
563 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
565 return wpa_ctrl_command(ctrl, buf);
567 #endif /* CONFIG_WPS */
570 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
577 printf("Invalid 'disassoc_imminent' command - two arguments "
578 "(STA addr and Disassociation Timer) are needed\n");
582 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
584 if (res < 0 || res >= (int) sizeof(buf))
586 return wpa_ctrl_command(ctrl, buf);
590 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
597 printf("Invalid 'ess_disassoc' command - two arguments (STA "
598 "addr and URL) are needed\n");
602 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
604 if (res < 0 || res >= (int) sizeof(buf))
606 return wpa_ctrl_command(ctrl, buf);
610 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
613 return wpa_ctrl_command(ctrl, "GET_CONFIG");
617 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
618 char *addr, size_t addr_len)
620 char buf[4096], *pos;
624 if (ctrl_conn == NULL) {
625 printf("Not connected to hostapd - command dropped.\n");
628 len = sizeof(buf) - 1;
629 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
632 printf("'%s' command timed out.\n", cmd);
634 } else if (ret < 0) {
635 printf("'%s' command failed.\n", cmd);
640 if (memcmp(buf, "FAIL", 4) == 0)
645 while (*pos != '\0' && *pos != '\n')
648 os_strlcpy(addr, buf, addr_len);
653 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
656 char addr[32], cmd[64];
658 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
661 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
662 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
668 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
670 printf("%s", commands_help);
675 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
678 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
683 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
685 hostapd_cli_quit = 1;
692 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
696 printf("Invalid LEVEL command: needs one argument (debug "
700 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
701 return wpa_ctrl_command(ctrl, cmd);
705 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
710 dir = opendir(ctrl_iface_dir);
712 printf("Control interface directory '%s' could not be "
713 "openned.\n", ctrl_iface_dir);
717 printf("Available interfaces:\n");
718 while ((dent = readdir(dir))) {
719 if (strcmp(dent->d_name, ".") == 0 ||
720 strcmp(dent->d_name, "..") == 0)
722 printf("%s\n", dent->d_name);
728 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
732 hostapd_cli_list_interfaces(ctrl);
736 hostapd_cli_close_connection();
738 ctrl_ifname = strdup(argv[0]);
740 if (hostapd_cli_open_connection(ctrl_ifname)) {
741 printf("Connected to interface '%s.\n", ctrl_ifname);
742 if (wpa_ctrl_attach(ctrl_conn) == 0) {
743 hostapd_cli_attached = 1;
745 printf("Warning: Failed to attach to "
749 printf("Could not connect to interface '%s' - re-trying\n",
756 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
762 printf("Invalid SET command: needs two arguments (variable "
763 "name and value)\n");
767 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
768 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
769 printf("Too long SET command.\n");
772 return wpa_ctrl_command(ctrl, cmd);
776 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
782 printf("Invalid GET command: needs one argument (variable "
787 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
788 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
789 printf("Too long GET command.\n");
792 return wpa_ctrl_command(ctrl, cmd);
796 struct hostapd_cli_cmd {
798 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
801 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
802 { "ping", hostapd_cli_cmd_ping },
803 { "mib", hostapd_cli_cmd_mib },
804 { "relog", hostapd_cli_cmd_relog },
805 { "sta", hostapd_cli_cmd_sta },
806 { "all_sta", hostapd_cli_cmd_all_sta },
807 { "new_sta", hostapd_cli_cmd_new_sta },
808 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
809 { "disassociate", hostapd_cli_cmd_disassociate },
810 #ifdef CONFIG_IEEE80211W
811 { "sa_query", hostapd_cli_cmd_sa_query },
812 #endif /* CONFIG_IEEE80211W */
814 { "wps_pin", hostapd_cli_cmd_wps_pin },
815 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
816 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
817 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
818 #ifdef CONFIG_WPS_NFC
819 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
820 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
821 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
822 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
823 #endif /* CONFIG_WPS_NFC */
824 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
825 { "wps_config", hostapd_cli_cmd_wps_config },
826 #endif /* CONFIG_WPS */
827 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
828 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
829 { "get_config", hostapd_cli_cmd_get_config },
830 { "help", hostapd_cli_cmd_help },
831 { "interface", hostapd_cli_cmd_interface },
832 { "level", hostapd_cli_cmd_level },
833 { "license", hostapd_cli_cmd_license },
834 { "quit", hostapd_cli_cmd_quit },
835 { "set", hostapd_cli_cmd_set },
836 { "get", hostapd_cli_cmd_get },
841 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
843 struct hostapd_cli_cmd *cmd, *match = NULL;
847 cmd = hostapd_cli_commands;
849 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
851 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
852 /* we have an exact match */
862 printf("Ambiguous command '%s'; possible commands:", argv[0]);
863 cmd = hostapd_cli_commands;
865 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
867 printf(" %s", cmd->cmd);
872 } else if (count == 0) {
873 printf("Unknown command '%s'\n", argv[0]);
875 match->handler(ctrl, argc - 1, &argv[1]);
880 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
884 if (ctrl_conn == NULL)
886 while (wpa_ctrl_pending(ctrl)) {
888 size_t len = sizeof(buf) - 1;
889 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
892 hostapd_cli_action_process(buf, len);
894 if (in_read && first)
900 printf("Could not read pending message.\n");
909 static int tokenize_cmd(char *cmd, char *argv[])
922 if (argc == max_args)
925 char *pos2 = os_strrchr(pos, '"');
929 while (*pos != '\0' && *pos != ' ')
939 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
941 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
942 printf("Connection to hostapd lost - trying to reconnect\n");
943 hostapd_cli_close_connection();
946 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
948 printf("Connection to hostapd re-established\n");
949 if (wpa_ctrl_attach(ctrl_conn) == 0) {
950 hostapd_cli_attached = 1;
952 printf("Warning: Failed to attach to "
958 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
959 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
963 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
969 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
971 char *argv[max_args];
973 argc = tokenize_cmd(cmd, argv);
975 wpa_request(ctrl_conn, argc, argv);
979 static void hostapd_cli_edit_eof_cb(void *ctx)
985 static void hostapd_cli_interactive(void)
987 printf("\nInteractive mode\n\n");
989 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
990 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
991 NULL, NULL, NULL, NULL);
992 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
996 edit_deinit(NULL, NULL);
997 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1001 static void hostapd_cli_cleanup(void)
1003 hostapd_cli_close_connection();
1005 os_daemonize_terminate(pid_file);
1007 os_program_deinit();
1011 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1019 fd = wpa_ctrl_get_fd(ctrl);
1021 while (!hostapd_cli_quit) {
1024 tv.tv_sec = ping_interval;
1026 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1027 if (res < 0 && errno != EINTR) {
1032 if (FD_ISSET(fd, &rfds))
1033 hostapd_cli_recv_pending(ctrl, 0, 1);
1035 len = sizeof(buf) - 1;
1036 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1037 hostapd_cli_action_process) < 0 ||
1038 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1039 printf("hostapd did not reply to PING "
1040 "command - exiting\n");
1048 int main(int argc, char *argv[])
1050 int warning_displayed = 0;
1054 if (os_program_init())
1058 c = getopt(argc, argv, "a:BhG:i:p:v");
1063 action_file = optarg;
1069 ping_interval = atoi(optarg);
1075 printf("%s\n", hostapd_cli_version);
1078 os_free(ctrl_ifname);
1079 ctrl_ifname = os_strdup(optarg);
1082 ctrl_iface_dir = optarg;
1090 interactive = (argc == optind) && (action_file == NULL);
1093 printf("%s\n\n%s\n\n", hostapd_cli_version,
1094 hostapd_cli_license);
1101 if (ctrl_ifname == NULL) {
1102 struct dirent *dent;
1103 DIR *dir = opendir(ctrl_iface_dir);
1105 while ((dent = readdir(dir))) {
1106 if (os_strcmp(dent->d_name, ".") == 0
1108 os_strcmp(dent->d_name, "..") == 0)
1110 printf("Selected interface '%s'\n",
1112 ctrl_ifname = os_strdup(dent->d_name);
1118 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1120 if (warning_displayed)
1121 printf("Connection established.\n");
1126 perror("Failed to connect to hostapd - "
1131 if (!warning_displayed) {
1132 printf("Could not connect to hostapd - re-trying\n");
1133 warning_displayed = 1;
1139 if (interactive || action_file) {
1140 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1141 hostapd_cli_attached = 1;
1143 printf("Warning: Failed to attach to hostapd.\n");
1149 if (daemonize && os_daemonize(pid_file))
1153 hostapd_cli_interactive();
1154 else if (action_file)
1155 hostapd_cli_action(ctrl_conn);
1157 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1159 os_free(ctrl_ifname);
1161 hostapd_cli_cleanup();