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-2012, 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_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
77 #endif /* CONFIG_WPS_OOB */
79 " wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
80 " wps_nfc_config_token <WPS/NDEF> build NFC configuration token\n"
81 " wps_nfc_token <WPS/NDEF/enable/disable> manager NFC password token\n"
82 #endif /* CONFIG_WPS_NFC */
83 " wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
84 " wps_config <SSID> <auth> <encr> <key> configure AP\n"
85 #endif /* CONFIG_WPS */
86 " get_config show current configuration\n"
87 " help show this usage help\n"
88 " interface [ifname] show interfaces/select interface\n"
89 " level <debug level> change debug level\n"
90 " license show full hostapd_cli license\n"
91 " quit exit hostapd_cli\n";
93 static struct wpa_ctrl *ctrl_conn;
94 static int hostapd_cli_quit = 0;
95 static int hostapd_cli_attached = 0;
97 #ifndef CONFIG_CTRL_IFACE_DIR
98 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
99 #endif /* CONFIG_CTRL_IFACE_DIR */
100 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
102 static char *ctrl_ifname = NULL;
103 static const char *pid_file = NULL;
104 static const char *action_file = NULL;
105 static int ping_interval = 5;
106 static int interactive = 0;
109 static void usage(void)
111 fprintf(stderr, "%s\n", hostapd_cli_version);
114 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
116 " [-G<ping interval>] [command..]\n"
119 " -h help (show this usage text)\n"
120 " -v shown version information\n"
121 " -p<path> path to find control sockets (default: "
122 "/var/run/hostapd)\n"
123 " -a<file> run in daemon mode executing the action file "
126 " -B run a daemon in the background\n"
127 " -i<ifname> Interface to listen on (default: first "
128 "interface found in the\n"
135 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
143 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
144 cfile = malloc(flen);
147 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
149 ctrl_conn = wpa_ctrl_open(cfile);
155 static void hostapd_cli_close_connection(void)
157 if (ctrl_conn == NULL)
160 if (hostapd_cli_attached) {
161 wpa_ctrl_detach(ctrl_conn);
162 hostapd_cli_attached = 0;
164 wpa_ctrl_close(ctrl_conn);
169 static void hostapd_cli_msg_cb(char *msg, size_t len)
175 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
181 if (ctrl_conn == NULL) {
182 printf("Not connected to hostapd - command dropped.\n");
185 len = sizeof(buf) - 1;
186 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
189 printf("'%s' command timed out.\n", cmd);
191 } else if (ret < 0) {
192 printf("'%s' command failed.\n", cmd);
203 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
205 return _wpa_ctrl_command(ctrl, cmd, 1);
209 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
211 return wpa_ctrl_command(ctrl, "PING");
215 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
217 return wpa_ctrl_command(ctrl, "RELOG");
221 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
223 return wpa_ctrl_command(ctrl, "MIB");
227 static int hostapd_cli_exec(const char *program, const char *arg1,
235 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
236 cmd = os_malloc(len);
239 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
240 if (res < 0 || (size_t) res >= len) {
248 #endif /* _WIN32_WCE */
255 static void hostapd_cli_action_process(char *msg, size_t len)
261 pos = os_strchr(pos, '>');
268 hostapd_cli_exec(action_file, ctrl_ifname, pos);
272 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
276 printf("Invalid 'sta' command - exactly one argument, STA "
277 "address, is required.\n");
280 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
281 return wpa_ctrl_command(ctrl, buf);
285 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
290 printf("Invalid 'new_sta' command - exactly one argument, STA "
291 "address, is required.\n");
294 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
295 return wpa_ctrl_command(ctrl, buf);
299 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
304 printf("Invalid 'deauthenticate' command - exactly one "
305 "argument, STA address, is required.\n");
309 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
312 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
313 return wpa_ctrl_command(ctrl, buf);
317 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
322 printf("Invalid 'disassociate' command - exactly one "
323 "argument, STA address, is required.\n");
327 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
330 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
331 return wpa_ctrl_command(ctrl, buf);
335 #ifdef CONFIG_IEEE80211W
336 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
341 printf("Invalid 'sa_query' command - exactly one argument, "
342 "STA address, is required.\n");
345 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
346 return wpa_ctrl_command(ctrl, buf);
348 #endif /* CONFIG_IEEE80211W */
352 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
357 printf("Invalid 'wps_pin' command - at least two arguments, "
358 "UUID and PIN, are required.\n");
362 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
363 argv[0], argv[1], argv[2], argv[3]);
365 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
366 argv[0], argv[1], argv[2]);
368 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
369 return wpa_ctrl_command(ctrl, buf);
373 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
379 if (argc != 1 && argc != 2) {
380 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
381 "- PIN to be verified\n");
386 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
389 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
391 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
392 printf("Too long WPS_CHECK_PIN command.\n");
395 return wpa_ctrl_command(ctrl, cmd);
399 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
402 return wpa_ctrl_command(ctrl, "WPS_PBC");
406 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
409 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
413 #ifdef CONFIG_WPS_OOB
414 static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
420 if (argc != 3 && argc != 4) {
421 printf("Invalid WPS_OOB command: need three or four "
423 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
424 "- PATH: path of OOB device like '/mnt'\n"
425 "- METHOD: OOB method 'pin-e' or 'pin-r', "
427 "- DEV_NAME: (only for NFC) device name like "
433 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
434 argv[0], argv[1], argv[2]);
436 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
437 argv[0], argv[1], argv[2], argv[3]);
438 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
439 printf("Too long WPS_OOB command.\n");
442 return wpa_ctrl_command(ctrl, cmd);
444 #endif /* CONFIG_WPS_OOB */
447 #ifdef CONFIG_WPS_NFC
448 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
456 printf("Invalid 'wps_nfc_tag_read' command - one argument "
461 buflen = 18 + os_strlen(argv[0]);
462 buf = os_malloc(buflen);
465 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
467 ret = wpa_ctrl_command(ctrl, buf);
474 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
475 int argc, char *argv[])
481 printf("Invalid 'wps_nfc_config_token' command - one argument "
486 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
488 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
489 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
492 return wpa_ctrl_command(ctrl, cmd);
496 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
497 int argc, char *argv[])
503 printf("Invalid 'wps_nfc_token' command - one argument is "
508 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
509 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
510 printf("Too long WPS_NFC_TOKEN command.\n");
513 return wpa_ctrl_command(ctrl, cmd);
515 #endif /* CONFIG_WPS_NFC */
518 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
523 printf("Invalid 'wps_ap_pin' command - at least one argument "
528 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
529 argv[0], argv[1], argv[2]);
531 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
534 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
535 return wpa_ctrl_command(ctrl, buf);
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_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
591 printf("Invalid 'ess_disassoc' command - two arguments (STA "
592 "addr and URL) are needed\n");
596 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
598 if (res < 0 || res >= (int) sizeof(buf))
600 return wpa_ctrl_command(ctrl, buf);
604 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
607 return wpa_ctrl_command(ctrl, "GET_CONFIG");
611 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
612 char *addr, size_t addr_len)
614 char buf[4096], *pos;
618 if (ctrl_conn == NULL) {
619 printf("Not connected to hostapd - command dropped.\n");
622 len = sizeof(buf) - 1;
623 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
626 printf("'%s' command timed out.\n", cmd);
628 } else if (ret < 0) {
629 printf("'%s' command failed.\n", cmd);
634 if (memcmp(buf, "FAIL", 4) == 0)
639 while (*pos != '\0' && *pos != '\n')
642 os_strlcpy(addr, buf, addr_len);
647 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
650 char addr[32], cmd[64];
652 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
655 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
656 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
662 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
664 printf("%s", commands_help);
669 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
672 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
677 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
679 hostapd_cli_quit = 1;
686 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
690 printf("Invalid LEVEL command: needs one argument (debug "
694 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
695 return wpa_ctrl_command(ctrl, cmd);
699 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
704 dir = opendir(ctrl_iface_dir);
706 printf("Control interface directory '%s' could not be "
707 "openned.\n", ctrl_iface_dir);
711 printf("Available interfaces:\n");
712 while ((dent = readdir(dir))) {
713 if (strcmp(dent->d_name, ".") == 0 ||
714 strcmp(dent->d_name, "..") == 0)
716 printf("%s\n", dent->d_name);
722 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
726 hostapd_cli_list_interfaces(ctrl);
730 hostapd_cli_close_connection();
732 ctrl_ifname = strdup(argv[0]);
734 if (hostapd_cli_open_connection(ctrl_ifname)) {
735 printf("Connected to interface '%s.\n", ctrl_ifname);
736 if (wpa_ctrl_attach(ctrl_conn) == 0) {
737 hostapd_cli_attached = 1;
739 printf("Warning: Failed to attach to "
743 printf("Could not connect to interface '%s' - re-trying\n",
750 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
756 printf("Invalid SET command: needs two arguments (variable "
757 "name and value)\n");
761 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
762 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
763 printf("Too long SET command.\n");
766 return wpa_ctrl_command(ctrl, cmd);
770 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
776 printf("Invalid GET command: needs one argument (variable "
781 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
782 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
783 printf("Too long GET command.\n");
786 return wpa_ctrl_command(ctrl, cmd);
790 struct hostapd_cli_cmd {
792 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
795 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
796 { "ping", hostapd_cli_cmd_ping },
797 { "mib", hostapd_cli_cmd_mib },
798 { "relog", hostapd_cli_cmd_relog },
799 { "sta", hostapd_cli_cmd_sta },
800 { "all_sta", hostapd_cli_cmd_all_sta },
801 { "new_sta", hostapd_cli_cmd_new_sta },
802 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
803 { "disassociate", hostapd_cli_cmd_disassociate },
804 #ifdef CONFIG_IEEE80211W
805 { "sa_query", hostapd_cli_cmd_sa_query },
806 #endif /* CONFIG_IEEE80211W */
808 { "wps_pin", hostapd_cli_cmd_wps_pin },
809 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
810 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
811 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
812 #ifdef CONFIG_WPS_OOB
813 { "wps_oob", hostapd_cli_cmd_wps_oob },
814 #endif /* CONFIG_WPS_OOB */
815 #ifdef CONFIG_WPS_NFC
816 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
817 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
818 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
819 #endif /* CONFIG_WPS_NFC */
820 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
821 { "wps_config", hostapd_cli_cmd_wps_config },
822 #endif /* CONFIG_WPS */
823 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
824 { "get_config", hostapd_cli_cmd_get_config },
825 { "help", hostapd_cli_cmd_help },
826 { "interface", hostapd_cli_cmd_interface },
827 { "level", hostapd_cli_cmd_level },
828 { "license", hostapd_cli_cmd_license },
829 { "quit", hostapd_cli_cmd_quit },
830 { "set", hostapd_cli_cmd_set },
831 { "get", hostapd_cli_cmd_get },
836 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
838 struct hostapd_cli_cmd *cmd, *match = NULL;
842 cmd = hostapd_cli_commands;
844 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
846 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
847 /* we have an exact match */
857 printf("Ambiguous command '%s'; possible commands:", argv[0]);
858 cmd = hostapd_cli_commands;
860 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
862 printf(" %s", cmd->cmd);
867 } else if (count == 0) {
868 printf("Unknown command '%s'\n", argv[0]);
870 match->handler(ctrl, argc - 1, &argv[1]);
875 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
879 if (ctrl_conn == NULL)
881 while (wpa_ctrl_pending(ctrl)) {
883 size_t len = sizeof(buf) - 1;
884 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
887 hostapd_cli_action_process(buf, len);
889 if (in_read && first)
895 printf("Could not read pending message.\n");
904 static int tokenize_cmd(char *cmd, char *argv[])
917 if (argc == max_args)
920 char *pos2 = os_strrchr(pos, '"');
924 while (*pos != '\0' && *pos != ' ')
934 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
936 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
937 printf("Connection to hostapd lost - trying to reconnect\n");
938 hostapd_cli_close_connection();
941 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
943 printf("Connection to hostapd re-established\n");
944 if (wpa_ctrl_attach(ctrl_conn) == 0) {
945 hostapd_cli_attached = 1;
947 printf("Warning: Failed to attach to "
953 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
954 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
958 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
964 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
966 char *argv[max_args];
968 argc = tokenize_cmd(cmd, argv);
970 wpa_request(ctrl_conn, argc, argv);
974 static void hostapd_cli_edit_eof_cb(void *ctx)
980 static void hostapd_cli_interactive(void)
982 printf("\nInteractive mode\n\n");
984 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
985 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
986 NULL, NULL, NULL, NULL);
987 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
991 edit_deinit(NULL, NULL);
992 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
996 static void hostapd_cli_cleanup(void)
998 hostapd_cli_close_connection();
1000 os_daemonize_terminate(pid_file);
1002 os_program_deinit();
1006 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1014 fd = wpa_ctrl_get_fd(ctrl);
1016 while (!hostapd_cli_quit) {
1019 tv.tv_sec = ping_interval;
1021 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1022 if (res < 0 && errno != EINTR) {
1027 if (FD_ISSET(fd, &rfds))
1028 hostapd_cli_recv_pending(ctrl, 0, 1);
1030 len = sizeof(buf) - 1;
1031 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1032 hostapd_cli_action_process) < 0 ||
1033 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1034 printf("hostapd did not reply to PING "
1035 "command - exiting\n");
1043 int main(int argc, char *argv[])
1045 int warning_displayed = 0;
1049 if (os_program_init())
1053 c = getopt(argc, argv, "a:BhG:i:p:v");
1058 action_file = optarg;
1064 ping_interval = atoi(optarg);
1070 printf("%s\n", hostapd_cli_version);
1073 os_free(ctrl_ifname);
1074 ctrl_ifname = os_strdup(optarg);
1077 ctrl_iface_dir = optarg;
1085 interactive = (argc == optind) && (action_file == NULL);
1088 printf("%s\n\n%s\n\n", hostapd_cli_version,
1089 hostapd_cli_license);
1096 if (ctrl_ifname == NULL) {
1097 struct dirent *dent;
1098 DIR *dir = opendir(ctrl_iface_dir);
1100 while ((dent = readdir(dir))) {
1101 if (os_strcmp(dent->d_name, ".") == 0
1103 os_strcmp(dent->d_name, "..") == 0)
1105 printf("Selected interface '%s'\n",
1107 ctrl_ifname = os_strdup(dent->d_name);
1113 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1115 if (warning_displayed)
1116 printf("Connection established.\n");
1121 perror("Failed to connect to hostapd - "
1126 if (!warning_displayed) {
1127 printf("Could not connect to hostapd - re-trying\n");
1128 warning_displayed = 1;
1134 if (interactive || action_file) {
1135 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1136 hostapd_cli_attached = 1;
1138 printf("Warning: Failed to attach to hostapd.\n");
1144 if (daemonize && os_daemonize(pid_file))
1148 hostapd_cli_interactive();
1149 else if (action_file)
1150 hostapd_cli_action(ctrl_conn);
1152 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1154 os_free(ctrl_ifname);
1156 hostapd_cli_cleanup();