2 * hostapd - command line interface for hostapd daemon
3 * Copyright (c) 2004-2011, 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"
75 " wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
76 #endif /* CONFIG_WPS_OOB */
77 " wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
78 " wps_config <SSID> <auth> <encr> <key> configure AP\n"
79 #endif /* CONFIG_WPS */
80 " get_config show current configuration\n"
81 " help show this usage help\n"
82 " interface [ifname] show interfaces/select interface\n"
83 " level <debug level> change debug level\n"
84 " license show full hostapd_cli license\n"
85 " quit exit hostapd_cli\n";
87 static struct wpa_ctrl
*ctrl_conn
;
88 static int hostapd_cli_quit
= 0;
89 static int hostapd_cli_attached
= 0;
90 static const char *ctrl_iface_dir
= "/var/run/hostapd";
91 static char *ctrl_ifname
= NULL
;
92 static const char *pid_file
= NULL
;
93 static const char *action_file
= NULL
;
94 static int ping_interval
= 5;
95 static int interactive
= 0;
98 static void usage(void)
100 fprintf(stderr
, "%s\n", hostapd_cli_version
);
103 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
105 " [-G<ping interval>] [command..]\n"
108 " -h help (show this usage text)\n"
109 " -v shown version information\n"
110 " -p<path> path to find control sockets (default: "
111 "/var/run/hostapd)\n"
112 " -a<file> run in daemon mode executing the action file "
115 " -B run a daemon in the background\n"
116 " -i<ifname> Interface to listen on (default: first "
117 "interface found in the\n"
124 static struct wpa_ctrl
* hostapd_cli_open_connection(const char *ifname
)
132 flen
= strlen(ctrl_iface_dir
) + strlen(ifname
) + 2;
133 cfile
= malloc(flen
);
136 snprintf(cfile
, flen
, "%s/%s", ctrl_iface_dir
, ifname
);
138 ctrl_conn
= wpa_ctrl_open(cfile
);
144 static void hostapd_cli_close_connection(void)
146 if (ctrl_conn
== NULL
)
149 if (hostapd_cli_attached
) {
150 wpa_ctrl_detach(ctrl_conn
);
151 hostapd_cli_attached
= 0;
153 wpa_ctrl_close(ctrl_conn
);
158 static void hostapd_cli_msg_cb(char *msg
, size_t len
)
164 static int _wpa_ctrl_command(struct wpa_ctrl
*ctrl
, char *cmd
, int print
)
170 if (ctrl_conn
== NULL
) {
171 printf("Not connected to hostapd - command dropped.\n");
174 len
= sizeof(buf
) - 1;
175 ret
= wpa_ctrl_request(ctrl
, cmd
, strlen(cmd
), buf
, &len
,
178 printf("'%s' command timed out.\n", cmd
);
180 } else if (ret
< 0) {
181 printf("'%s' command failed.\n", cmd
);
192 static inline int wpa_ctrl_command(struct wpa_ctrl
*ctrl
, char *cmd
)
194 return _wpa_ctrl_command(ctrl
, cmd
, 1);
198 static int hostapd_cli_cmd_ping(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
200 return wpa_ctrl_command(ctrl
, "PING");
204 static int hostapd_cli_cmd_relog(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
206 return wpa_ctrl_command(ctrl
, "RELOG");
210 static int hostapd_cli_cmd_mib(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
212 return wpa_ctrl_command(ctrl
, "MIB");
216 static int hostapd_cli_exec(const char *program
, const char *arg1
,
224 len
= os_strlen(program
) + os_strlen(arg1
) + os_strlen(arg2
) + 3;
225 cmd
= os_malloc(len
);
228 res
= os_snprintf(cmd
, len
, "%s %s %s", program
, arg1
, arg2
);
229 if (res
< 0 || (size_t) res
>= len
) {
237 #endif /* _WIN32_WCE */
244 static void hostapd_cli_action_process(char *msg
, size_t len
)
250 pos
= os_strchr(pos
, '>');
257 hostapd_cli_exec(action_file
, ctrl_ifname
, pos
);
261 static int hostapd_cli_cmd_sta(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
265 printf("Invalid 'sta' command - exactly one argument, STA "
266 "address, is required.\n");
269 snprintf(buf
, sizeof(buf
), "STA %s", argv
[0]);
270 return wpa_ctrl_command(ctrl
, buf
);
274 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl
*ctrl
, int argc
,
279 printf("Invalid 'new_sta' command - exactly one argument, STA "
280 "address, is required.\n");
283 snprintf(buf
, sizeof(buf
), "NEW_STA %s", argv
[0]);
284 return wpa_ctrl_command(ctrl
, buf
);
288 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl
*ctrl
, int argc
,
293 printf("Invalid 'deauthenticate' command - exactly one "
294 "argument, STA address, is required.\n");
298 os_snprintf(buf
, sizeof(buf
), "DEAUTHENTICATE %s %s",
301 os_snprintf(buf
, sizeof(buf
), "DEAUTHENTICATE %s", argv
[0]);
302 return wpa_ctrl_command(ctrl
, buf
);
306 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl
*ctrl
, int argc
,
311 printf("Invalid 'disassociate' command - exactly one "
312 "argument, STA address, is required.\n");
316 os_snprintf(buf
, sizeof(buf
), "DISASSOCIATE %s %s",
319 os_snprintf(buf
, sizeof(buf
), "DISASSOCIATE %s", argv
[0]);
320 return wpa_ctrl_command(ctrl
, buf
);
324 #ifdef CONFIG_IEEE80211W
325 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl
*ctrl
, int argc
,
330 printf("Invalid 'sa_query' command - exactly one argument, "
331 "STA address, is required.\n");
334 snprintf(buf
, sizeof(buf
), "SA_QUERY %s", argv
[0]);
335 return wpa_ctrl_command(ctrl
, buf
);
337 #endif /* CONFIG_IEEE80211W */
341 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl
*ctrl
, int argc
,
346 printf("Invalid 'wps_pin' command - at least two arguments, "
347 "UUID and PIN, are required.\n");
351 snprintf(buf
, sizeof(buf
), "WPS_PIN %s %s %s %s",
352 argv
[0], argv
[1], argv
[2], argv
[3]);
354 snprintf(buf
, sizeof(buf
), "WPS_PIN %s %s %s",
355 argv
[0], argv
[1], argv
[2]);
357 snprintf(buf
, sizeof(buf
), "WPS_PIN %s %s", argv
[0], argv
[1]);
358 return wpa_ctrl_command(ctrl
, buf
);
362 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl
*ctrl
, int argc
,
368 if (argc
!= 1 && argc
!= 2) {
369 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
370 "- PIN to be verified\n");
375 res
= os_snprintf(cmd
, sizeof(cmd
), "WPS_CHECK_PIN %s %s",
378 res
= os_snprintf(cmd
, sizeof(cmd
), "WPS_CHECK_PIN %s",
380 if (res
< 0 || (size_t) res
>= sizeof(cmd
) - 1) {
381 printf("Too long WPS_CHECK_PIN command.\n");
384 return wpa_ctrl_command(ctrl
, cmd
);
388 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl
*ctrl
, int argc
,
391 return wpa_ctrl_command(ctrl
, "WPS_PBC");
395 #ifdef CONFIG_WPS_OOB
396 static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl
*ctrl
, int argc
,
402 if (argc
!= 3 && argc
!= 4) {
403 printf("Invalid WPS_OOB command: need three or four "
405 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
406 "- PATH: path of OOB device like '/mnt'\n"
407 "- METHOD: OOB method 'pin-e' or 'pin-r', "
409 "- DEV_NAME: (only for NFC) device name like "
415 res
= os_snprintf(cmd
, sizeof(cmd
), "WPS_OOB %s %s %s",
416 argv
[0], argv
[1], argv
[2]);
418 res
= os_snprintf(cmd
, sizeof(cmd
), "WPS_OOB %s %s %s %s",
419 argv
[0], argv
[1], argv
[2], argv
[3]);
420 if (res
< 0 || (size_t) res
>= sizeof(cmd
) - 1) {
421 printf("Too long WPS_OOB command.\n");
424 return wpa_ctrl_command(ctrl
, cmd
);
426 #endif /* CONFIG_WPS_OOB */
429 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl
*ctrl
, int argc
,
434 printf("Invalid 'wps_ap_pin' command - at least one argument "
439 snprintf(buf
, sizeof(buf
), "WPS_AP_PIN %s %s %s",
440 argv
[0], argv
[1], argv
[2]);
442 snprintf(buf
, sizeof(buf
), "WPS_AP_PIN %s %s",
445 snprintf(buf
, sizeof(buf
), "WPS_AP_PIN %s", argv
[0]);
446 return wpa_ctrl_command(ctrl
, buf
);
450 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl
*ctrl
, int argc
,
454 char ssid_hex
[2 * 32 + 1];
455 char key_hex
[2 * 64 + 1];
459 printf("Invalid 'wps_config' command - at least two arguments "
465 for (i
= 0; i
< 32; i
++) {
466 if (argv
[0][i
] == '\0')
468 os_snprintf(&ssid_hex
[i
* 2], 3, "%02x", argv
[0][i
]);
473 for (i
= 0; i
< 64; i
++) {
474 if (argv
[3][i
] == '\0')
476 os_snprintf(&key_hex
[i
* 2], 3, "%02x",
482 snprintf(buf
, sizeof(buf
), "WPS_CONFIG %s %s %s %s",
483 ssid_hex
, argv
[1], argv
[2], key_hex
);
485 snprintf(buf
, sizeof(buf
), "WPS_CONFIG %s %s %s",
486 ssid_hex
, argv
[1], argv
[2]);
488 snprintf(buf
, sizeof(buf
), "WPS_CONFIG %s %s",
490 return wpa_ctrl_command(ctrl
, buf
);
492 #endif /* CONFIG_WPS */
495 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl
*ctrl
, int argc
,
502 printf("Invalid 'ess_disassoc' command - two arguments (STA "
503 "addr and URL) are needed\n");
507 res
= os_snprintf(buf
, sizeof(buf
), "ESS_DISASSOC %s %s",
509 if (res
< 0 || res
>= (int) sizeof(buf
))
511 return wpa_ctrl_command(ctrl
, buf
);
515 static int hostapd_cli_cmd_get_config(struct wpa_ctrl
*ctrl
, int argc
,
518 return wpa_ctrl_command(ctrl
, "GET_CONFIG");
522 static int wpa_ctrl_command_sta(struct wpa_ctrl
*ctrl
, char *cmd
,
523 char *addr
, size_t addr_len
)
525 char buf
[4096], *pos
;
529 if (ctrl_conn
== NULL
) {
530 printf("Not connected to hostapd - command dropped.\n");
533 len
= sizeof(buf
) - 1;
534 ret
= wpa_ctrl_request(ctrl
, cmd
, strlen(cmd
), buf
, &len
,
537 printf("'%s' command timed out.\n", cmd
);
539 } else if (ret
< 0) {
540 printf("'%s' command failed.\n", cmd
);
545 if (memcmp(buf
, "FAIL", 4) == 0)
550 while (*pos
!= '\0' && *pos
!= '\n')
553 os_strlcpy(addr
, buf
, addr_len
);
558 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl
*ctrl
, int argc
,
561 char addr
[32], cmd
[64];
563 if (wpa_ctrl_command_sta(ctrl
, "STA-FIRST", addr
, sizeof(addr
)))
566 snprintf(cmd
, sizeof(cmd
), "STA-NEXT %s", addr
);
567 } while (wpa_ctrl_command_sta(ctrl
, cmd
, addr
, sizeof(addr
)) == 0);
573 static int hostapd_cli_cmd_help(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
575 printf("%s", commands_help
);
580 static int hostapd_cli_cmd_license(struct wpa_ctrl
*ctrl
, int argc
,
583 printf("%s\n\n%s\n", hostapd_cli_version
, hostapd_cli_full_license
);
588 static int hostapd_cli_cmd_quit(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
590 hostapd_cli_quit
= 1;
597 static int hostapd_cli_cmd_level(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
601 printf("Invalid LEVEL command: needs one argument (debug "
605 snprintf(cmd
, sizeof(cmd
), "LEVEL %s", argv
[0]);
606 return wpa_ctrl_command(ctrl
, cmd
);
610 static void hostapd_cli_list_interfaces(struct wpa_ctrl
*ctrl
)
615 dir
= opendir(ctrl_iface_dir
);
617 printf("Control interface directory '%s' could not be "
618 "openned.\n", ctrl_iface_dir
);
622 printf("Available interfaces:\n");
623 while ((dent
= readdir(dir
))) {
624 if (strcmp(dent
->d_name
, ".") == 0 ||
625 strcmp(dent
->d_name
, "..") == 0)
627 printf("%s\n", dent
->d_name
);
633 static int hostapd_cli_cmd_interface(struct wpa_ctrl
*ctrl
, int argc
,
637 hostapd_cli_list_interfaces(ctrl
);
641 hostapd_cli_close_connection();
643 ctrl_ifname
= strdup(argv
[0]);
645 if (hostapd_cli_open_connection(ctrl_ifname
)) {
646 printf("Connected to interface '%s.\n", ctrl_ifname
);
647 if (wpa_ctrl_attach(ctrl_conn
) == 0) {
648 hostapd_cli_attached
= 1;
650 printf("Warning: Failed to attach to "
654 printf("Could not connect to interface '%s' - re-trying\n",
661 static int hostapd_cli_cmd_set(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
667 printf("Invalid SET command: needs two arguments (variable "
668 "name and value)\n");
672 res
= os_snprintf(cmd
, sizeof(cmd
), "SET %s %s", argv
[0], argv
[1]);
673 if (res
< 0 || (size_t) res
>= sizeof(cmd
) - 1) {
674 printf("Too long SET command.\n");
677 return wpa_ctrl_command(ctrl
, cmd
);
681 static int hostapd_cli_cmd_get(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
687 printf("Invalid GET command: needs one argument (variable "
692 res
= os_snprintf(cmd
, sizeof(cmd
), "GET %s", argv
[0]);
693 if (res
< 0 || (size_t) res
>= sizeof(cmd
) - 1) {
694 printf("Too long GET command.\n");
697 return wpa_ctrl_command(ctrl
, cmd
);
701 struct hostapd_cli_cmd
{
703 int (*handler
)(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[]);
706 static struct hostapd_cli_cmd hostapd_cli_commands
[] = {
707 { "ping", hostapd_cli_cmd_ping
},
708 { "mib", hostapd_cli_cmd_mib
},
709 { "relog", hostapd_cli_cmd_relog
},
710 { "sta", hostapd_cli_cmd_sta
},
711 { "all_sta", hostapd_cli_cmd_all_sta
},
712 { "new_sta", hostapd_cli_cmd_new_sta
},
713 { "deauthenticate", hostapd_cli_cmd_deauthenticate
},
714 { "disassociate", hostapd_cli_cmd_disassociate
},
715 #ifdef CONFIG_IEEE80211W
716 { "sa_query", hostapd_cli_cmd_sa_query
},
717 #endif /* CONFIG_IEEE80211W */
719 { "wps_pin", hostapd_cli_cmd_wps_pin
},
720 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin
},
721 { "wps_pbc", hostapd_cli_cmd_wps_pbc
},
722 #ifdef CONFIG_WPS_OOB
723 { "wps_oob", hostapd_cli_cmd_wps_oob
},
724 #endif /* CONFIG_WPS_OOB */
725 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin
},
726 { "wps_config", hostapd_cli_cmd_wps_config
},
727 #endif /* CONFIG_WPS */
728 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc
},
729 { "get_config", hostapd_cli_cmd_get_config
},
730 { "help", hostapd_cli_cmd_help
},
731 { "interface", hostapd_cli_cmd_interface
},
732 { "level", hostapd_cli_cmd_level
},
733 { "license", hostapd_cli_cmd_license
},
734 { "quit", hostapd_cli_cmd_quit
},
735 { "set", hostapd_cli_cmd_set
},
736 { "get", hostapd_cli_cmd_get
},
741 static void wpa_request(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
743 struct hostapd_cli_cmd
*cmd
, *match
= NULL
;
747 cmd
= hostapd_cli_commands
;
749 if (strncasecmp(cmd
->cmd
, argv
[0], strlen(argv
[0])) == 0) {
751 if (os_strcasecmp(cmd
->cmd
, argv
[0]) == 0) {
752 /* we have an exact match */
762 printf("Ambiguous command '%s'; possible commands:", argv
[0]);
763 cmd
= hostapd_cli_commands
;
765 if (strncasecmp(cmd
->cmd
, argv
[0], strlen(argv
[0])) ==
767 printf(" %s", cmd
->cmd
);
772 } else if (count
== 0) {
773 printf("Unknown command '%s'\n", argv
[0]);
775 match
->handler(ctrl
, argc
- 1, &argv
[1]);
780 static void hostapd_cli_recv_pending(struct wpa_ctrl
*ctrl
, int in_read
,
784 if (ctrl_conn
== NULL
)
786 while (wpa_ctrl_pending(ctrl
)) {
788 size_t len
= sizeof(buf
) - 1;
789 if (wpa_ctrl_recv(ctrl
, buf
, &len
) == 0) {
792 hostapd_cli_action_process(buf
, len
);
794 if (in_read
&& first
)
800 printf("Could not read pending message.\n");
809 static int tokenize_cmd(char *cmd
, char *argv
[])
822 if (argc
== max_args
)
825 char *pos2
= os_strrchr(pos
, '"');
829 while (*pos
!= '\0' && *pos
!= ' ')
839 static void hostapd_cli_ping(void *eloop_ctx
, void *timeout_ctx
)
841 if (ctrl_conn
&& _wpa_ctrl_command(ctrl_conn
, "PING", 0)) {
842 printf("Connection to hostapd lost - trying to reconnect\n");
843 hostapd_cli_close_connection();
846 ctrl_conn
= hostapd_cli_open_connection(ctrl_ifname
);
848 printf("Connection to hostapd re-established\n");
849 if (wpa_ctrl_attach(ctrl_conn
) == 0) {
850 hostapd_cli_attached
= 1;
852 printf("Warning: Failed to attach to "
858 hostapd_cli_recv_pending(ctrl_conn
, 1, 0);
859 eloop_register_timeout(ping_interval
, 0, hostapd_cli_ping
, NULL
, NULL
);
863 static void hostapd_cli_eloop_terminate(int sig
, void *signal_ctx
)
869 static void hostapd_cli_edit_cmd_cb(void *ctx
, char *cmd
)
871 char *argv
[max_args
];
873 argc
= tokenize_cmd(cmd
, argv
);
875 wpa_request(ctrl_conn
, argc
, argv
);
879 static void hostapd_cli_edit_eof_cb(void *ctx
)
885 static void hostapd_cli_interactive(void)
887 printf("\nInteractive mode\n\n");
889 eloop_register_signal_terminate(hostapd_cli_eloop_terminate
, NULL
);
890 edit_init(hostapd_cli_edit_cmd_cb
, hostapd_cli_edit_eof_cb
,
892 eloop_register_timeout(ping_interval
, 0, hostapd_cli_ping
, NULL
, NULL
);
896 edit_deinit(NULL
, NULL
);
897 eloop_cancel_timeout(hostapd_cli_ping
, NULL
, NULL
);
901 static void hostapd_cli_cleanup(void)
903 hostapd_cli_close_connection();
905 os_daemonize_terminate(pid_file
);
911 static void hostapd_cli_action(struct wpa_ctrl
*ctrl
)
919 fd
= wpa_ctrl_get_fd(ctrl
);
921 while (!hostapd_cli_quit
) {
924 tv
.tv_sec
= ping_interval
;
926 res
= select(fd
+ 1, &rfds
, NULL
, NULL
, &tv
);
927 if (res
< 0 && errno
!= EINTR
) {
932 if (FD_ISSET(fd
, &rfds
))
933 hostapd_cli_recv_pending(ctrl
, 0, 1);
935 len
= sizeof(buf
) - 1;
936 if (wpa_ctrl_request(ctrl
, "PING", 4, buf
, &len
,
937 hostapd_cli_action_process
) < 0 ||
938 len
< 4 || os_memcmp(buf
, "PONG", 4) != 0) {
939 printf("hostapd did not reply to PING "
940 "command - exiting\n");
948 int main(int argc
, char *argv
[])
950 int warning_displayed
= 0;
954 if (os_program_init())
958 c
= getopt(argc
, argv
, "a:BhG:i:p:v");
963 action_file
= optarg
;
969 ping_interval
= atoi(optarg
);
975 printf("%s\n", hostapd_cli_version
);
978 os_free(ctrl_ifname
);
979 ctrl_ifname
= os_strdup(optarg
);
982 ctrl_iface_dir
= optarg
;
990 interactive
= (argc
== optind
) && (action_file
== NULL
);
993 printf("%s\n\n%s\n\n", hostapd_cli_version
,
994 hostapd_cli_license
);
1001 if (ctrl_ifname
== NULL
) {
1002 struct dirent
*dent
;
1003 DIR *dir
= opendir(ctrl_iface_dir
);
1005 while ((dent
= readdir(dir
))) {
1006 if (os_strcmp(dent
->d_name
, ".") == 0
1008 os_strcmp(dent
->d_name
, "..") == 0)
1010 printf("Selected interface '%s'\n",
1012 ctrl_ifname
= os_strdup(dent
->d_name
);
1018 ctrl_conn
= hostapd_cli_open_connection(ctrl_ifname
);
1020 if (warning_displayed
)
1021 printf("Connection established.\n");
1026 perror("Failed to connect to hostapd - "
1031 if (!warning_displayed
) {
1032 printf("Could not connect to hostapd - re-trying\n");
1033 warning_displayed
= 1;
1039 if (interactive
|| action_file
) {
1040 if (wpa_ctrl_attach(ctrl_conn
) == 0) {
1041 hostapd_cli_attached
= 1;
1043 printf("Warning: Failed to attach to hostapd.\n");
1049 if (daemonize
&& os_daemonize(pid_file
))
1053 hostapd_cli_interactive();
1054 else if (action_file
)
1055 hostapd_cli_action(ctrl_conn
);
1057 wpa_request(ctrl_conn
, argc
- optind
, &argv
[optind
]);
1059 os_free(ctrl_ifname
);
1061 hostapd_cli_cleanup();