2 * hostapd - command line interface for hostapd daemon
3 * Copyright (c) 2004-2015, 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-2015, 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 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
222 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
223 return wpa_ctrl_command(ctrl, "STATUS");
227 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
231 os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
232 return wpa_ctrl_command(ctrl, buf);
234 return wpa_ctrl_command(ctrl, "MIB");
238 static int hostapd_cli_exec(const char *program, const char *arg1,
245 len = os_strlen(arg1) + os_strlen(arg2) + 2;
246 arg = os_malloc(len);
249 os_snprintf(arg, len, "%s %s", arg1, arg2);
250 res = os_exec(program, arg, 1);
257 static void hostapd_cli_action_process(char *msg, size_t len)
263 pos = os_strchr(pos, '>');
270 hostapd_cli_exec(action_file, ctrl_ifname, pos);
274 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
278 printf("Invalid 'sta' command - at least one argument, STA "
279 "address, is required.\n");
283 snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
285 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
286 return wpa_ctrl_command(ctrl, buf);
290 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
295 printf("Invalid 'new_sta' command - exactly one argument, STA "
296 "address, is required.\n");
299 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
300 return wpa_ctrl_command(ctrl, buf);
304 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
309 printf("Invalid 'deauthenticate' command - exactly one "
310 "argument, STA address, is required.\n");
314 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
317 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
318 return wpa_ctrl_command(ctrl, buf);
322 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
327 printf("Invalid 'disassociate' command - exactly one "
328 "argument, STA address, is required.\n");
332 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
335 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
336 return wpa_ctrl_command(ctrl, buf);
340 #ifdef CONFIG_IEEE80211W
341 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
346 printf("Invalid 'sa_query' command - exactly one argument, "
347 "STA address, is required.\n");
350 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
351 return wpa_ctrl_command(ctrl, buf);
353 #endif /* CONFIG_IEEE80211W */
357 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
362 printf("Invalid 'wps_pin' command - at least two arguments, "
363 "UUID and PIN, are required.\n");
367 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
368 argv[0], argv[1], argv[2], argv[3]);
370 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
371 argv[0], argv[1], argv[2]);
373 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
374 return wpa_ctrl_command(ctrl, buf);
378 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
384 if (argc != 1 && argc != 2) {
385 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
386 "- PIN to be verified\n");
391 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
394 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
396 if (os_snprintf_error(sizeof(cmd), res)) {
397 printf("Too long WPS_CHECK_PIN command.\n");
400 return wpa_ctrl_command(ctrl, cmd);
404 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
407 return wpa_ctrl_command(ctrl, "WPS_PBC");
411 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
414 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
418 #ifdef CONFIG_WPS_NFC
419 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
427 printf("Invalid 'wps_nfc_tag_read' command - one argument "
432 buflen = 18 + os_strlen(argv[0]);
433 buf = os_malloc(buflen);
436 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
438 ret = wpa_ctrl_command(ctrl, buf);
445 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
446 int argc, char *argv[])
452 printf("Invalid 'wps_nfc_config_token' command - one argument "
457 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
459 if (os_snprintf_error(sizeof(cmd), res)) {
460 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
463 return wpa_ctrl_command(ctrl, cmd);
467 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
468 int argc, char *argv[])
474 printf("Invalid 'wps_nfc_token' command - one argument is "
479 res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
480 if (os_snprintf_error(sizeof(cmd), res)) {
481 printf("Too long WPS_NFC_TOKEN command.\n");
484 return wpa_ctrl_command(ctrl, cmd);
488 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
489 int argc, char *argv[])
495 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
500 res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
502 if (os_snprintf_error(sizeof(cmd), res)) {
503 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
506 return wpa_ctrl_command(ctrl, cmd);
509 #endif /* CONFIG_WPS_NFC */
512 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
517 printf("Invalid 'wps_ap_pin' command - at least one argument "
522 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
523 argv[0], argv[1], argv[2]);
525 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
528 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
529 return wpa_ctrl_command(ctrl, buf);
533 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
536 return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
540 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
544 char ssid_hex[2 * 32 + 1];
545 char key_hex[2 * 64 + 1];
549 printf("Invalid 'wps_config' command - at least two arguments "
555 for (i = 0; i < 32; i++) {
556 if (argv[0][i] == '\0')
558 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
563 for (i = 0; i < 64; i++) {
564 if (argv[3][i] == '\0')
566 os_snprintf(&key_hex[i * 2], 3, "%02x",
572 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
573 ssid_hex, argv[1], argv[2], key_hex);
575 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
576 ssid_hex, argv[1], argv[2]);
578 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
580 return wpa_ctrl_command(ctrl, buf);
582 #endif /* CONFIG_WPS */
585 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
592 printf("Invalid 'disassoc_imminent' command - two arguments "
593 "(STA addr and Disassociation Timer) are needed\n");
597 res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
599 if (os_snprintf_error(sizeof(buf), res))
601 return wpa_ctrl_command(ctrl, buf);
605 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
612 printf("Invalid 'ess_disassoc' command - three arguments (STA "
613 "addr, disassoc timer, and URL) are needed\n");
617 res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
618 argv[0], argv[1], argv[2]);
619 if (os_snprintf_error(sizeof(buf), res))
621 return wpa_ctrl_command(ctrl, buf);
625 static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
628 char buf[2000], *tmp;
632 printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
636 res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
637 if (os_snprintf_error(sizeof(buf), res))
641 for (i = 1; i < argc; i++) {
643 res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
644 if (os_snprintf_error(sizeof(buf) - total, res))
648 return wpa_ctrl_command(ctrl, buf);
652 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
655 return wpa_ctrl_command(ctrl, "GET_CONFIG");
659 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
660 char *addr, size_t addr_len)
662 char buf[4096], *pos;
666 if (ctrl_conn == NULL) {
667 printf("Not connected to hostapd - command dropped.\n");
670 len = sizeof(buf) - 1;
671 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
674 printf("'%s' command timed out.\n", cmd);
676 } else if (ret < 0) {
677 printf("'%s' command failed.\n", cmd);
682 if (memcmp(buf, "FAIL", 4) == 0)
687 while (*pos != '\0' && *pos != '\n')
690 os_strlcpy(addr, buf, addr_len);
695 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
698 char addr[32], cmd[64];
700 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
703 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
704 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
710 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
712 printf("%s", commands_help);
717 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
720 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
725 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
726 int argc, char *argv[])
732 printf("Invalid 'set_qos_map_set' command - "
733 "one argument (comma delimited QoS map set) "
738 res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
739 if (os_snprintf_error(sizeof(buf), res))
741 return wpa_ctrl_command(ctrl, buf);
745 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
746 int argc, char *argv[])
752 printf("Invalid 'send_qos_map_conf' command - "
753 "one argument (STA addr) is needed\n");
757 res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
758 if (os_snprintf_error(sizeof(buf), res))
760 return wpa_ctrl_command(ctrl, buf);
764 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
771 printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
772 "addr and URL) are needed\n");
776 res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
778 if (os_snprintf_error(sizeof(buf), res))
780 return wpa_ctrl_command(ctrl, buf);
784 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
791 printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
796 res = os_snprintf(buf, sizeof(buf),
797 "HS20_DEAUTH_REQ %s %s %s %s",
798 argv[0], argv[1], argv[2], argv[3]);
800 res = os_snprintf(buf, sizeof(buf),
801 "HS20_DEAUTH_REQ %s %s %s",
802 argv[0], argv[1], argv[2]);
803 if (os_snprintf_error(sizeof(buf), res))
805 return wpa_ctrl_command(ctrl, buf);
809 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
811 hostapd_cli_quit = 1;
818 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
822 printf("Invalid LEVEL command: needs one argument (debug "
826 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
827 return wpa_ctrl_command(ctrl, cmd);
831 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
836 dir = opendir(ctrl_iface_dir);
838 printf("Control interface directory '%s' could not be "
839 "openned.\n", ctrl_iface_dir);
843 printf("Available interfaces:\n");
844 while ((dent = readdir(dir))) {
845 if (strcmp(dent->d_name, ".") == 0 ||
846 strcmp(dent->d_name, "..") == 0)
848 printf("%s\n", dent->d_name);
854 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
858 hostapd_cli_list_interfaces(ctrl);
862 hostapd_cli_close_connection();
863 os_free(ctrl_ifname);
864 ctrl_ifname = os_strdup(argv[0]);
865 if (ctrl_ifname == NULL)
868 if (hostapd_cli_open_connection(ctrl_ifname)) {
869 printf("Connected to interface '%s.\n", ctrl_ifname);
870 if (wpa_ctrl_attach(ctrl_conn) == 0) {
871 hostapd_cli_attached = 1;
873 printf("Warning: Failed to attach to "
877 printf("Could not connect to interface '%s' - re-trying\n",
884 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
890 printf("Invalid SET command: needs two arguments (variable "
891 "name and value)\n");
895 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
896 if (os_snprintf_error(sizeof(cmd), res)) {
897 printf("Too long SET command.\n");
900 return wpa_ctrl_command(ctrl, cmd);
904 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
910 printf("Invalid GET command: needs one argument (variable "
915 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
916 if (os_snprintf_error(sizeof(cmd), res)) {
917 printf("Too long GET command.\n");
920 return wpa_ctrl_command(ctrl, cmd);
924 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
925 int argc, char *argv[])
934 printf("Invalid chan_switch command: needs at least two "
935 "arguments (count and freq)\n"
936 "usage: <cs_count> <freq> [sec_channel_offset=] "
937 "[center_freq1=] [center_freq2=] [bandwidth=] "
938 "[blocktx] [ht|vht]\n");
942 res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
944 if (os_snprintf_error(sizeof(cmd), res)) {
945 printf("Too long CHAN_SWITCH command.\n");
950 for (i = 2; i < argc; i++) {
952 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
953 if (os_snprintf_error(sizeof(cmd) - total, res)) {
954 printf("Too long CHAN_SWITCH command.\n");
959 return wpa_ctrl_command(ctrl, cmd);
963 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
966 return wpa_ctrl_command(ctrl, "ENABLE");
970 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
973 return wpa_ctrl_command(ctrl, "RELOAD");
977 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
980 return wpa_ctrl_command(ctrl, "DISABLE");
984 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
989 if (argc < 2 || argc > 3) {
990 printf("Invalid vendor command\n"
991 "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
995 res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
996 argc == 3 ? argv[2] : "");
997 if (os_snprintf_error(sizeof(cmd), res)) {
998 printf("Too long VENDOR command.\n");
1001 return wpa_ctrl_command(ctrl, cmd);
1005 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1008 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1012 struct hostapd_cli_cmd {
1014 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1017 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
1018 { "ping", hostapd_cli_cmd_ping },
1019 { "mib", hostapd_cli_cmd_mib },
1020 { "relog", hostapd_cli_cmd_relog },
1021 { "status", hostapd_cli_cmd_status },
1022 { "sta", hostapd_cli_cmd_sta },
1023 { "all_sta", hostapd_cli_cmd_all_sta },
1024 { "new_sta", hostapd_cli_cmd_new_sta },
1025 { "deauthenticate", hostapd_cli_cmd_deauthenticate },
1026 { "disassociate", hostapd_cli_cmd_disassociate },
1027 #ifdef CONFIG_IEEE80211W
1028 { "sa_query", hostapd_cli_cmd_sa_query },
1029 #endif /* CONFIG_IEEE80211W */
1031 { "wps_pin", hostapd_cli_cmd_wps_pin },
1032 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
1033 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
1034 { "wps_cancel", hostapd_cli_cmd_wps_cancel },
1035 #ifdef CONFIG_WPS_NFC
1036 { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
1037 { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
1038 { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
1039 { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
1040 #endif /* CONFIG_WPS_NFC */
1041 { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
1042 { "wps_config", hostapd_cli_cmd_wps_config },
1043 { "wps_get_status", hostapd_cli_cmd_wps_get_status },
1044 #endif /* CONFIG_WPS */
1045 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
1046 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
1047 { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
1048 { "get_config", hostapd_cli_cmd_get_config },
1049 { "help", hostapd_cli_cmd_help },
1050 { "interface", hostapd_cli_cmd_interface },
1051 { "level", hostapd_cli_cmd_level },
1052 { "license", hostapd_cli_cmd_license },
1053 { "quit", hostapd_cli_cmd_quit },
1054 { "set", hostapd_cli_cmd_set },
1055 { "get", hostapd_cli_cmd_get },
1056 { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
1057 { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
1058 { "chan_switch", hostapd_cli_cmd_chan_switch },
1059 { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
1060 { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
1061 { "vendor", hostapd_cli_cmd_vendor },
1062 { "enable", hostapd_cli_cmd_enable },
1063 { "reload", hostapd_cli_cmd_reload },
1064 { "disable", hostapd_cli_cmd_disable },
1065 { "erp_flush", hostapd_cli_cmd_erp_flush },
1070 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1072 struct hostapd_cli_cmd *cmd, *match = NULL;
1076 cmd = hostapd_cli_commands;
1078 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1080 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1081 /* we have an exact match */
1091 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1092 cmd = hostapd_cli_commands;
1094 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1096 printf(" %s", cmd->cmd);
1101 } else if (count == 0) {
1102 printf("Unknown command '%s'\n", argv[0]);
1104 match->handler(ctrl, argc - 1, &argv[1]);
1109 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1113 if (ctrl_conn == NULL)
1115 while (wpa_ctrl_pending(ctrl)) {
1117 size_t len = sizeof(buf) - 1;
1118 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1121 hostapd_cli_action_process(buf, len);
1123 if (in_read && first)
1126 printf("%s\n", buf);
1129 printf("Could not read pending message.\n");
1138 static int tokenize_cmd(char *cmd, char *argv[])
1151 if (argc == max_args)
1154 char *pos2 = os_strrchr(pos, '"');
1158 while (*pos != '\0' && *pos != ' ')
1168 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1170 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1171 printf("Connection to hostapd lost - trying to reconnect\n");
1172 hostapd_cli_close_connection();
1175 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1177 printf("Connection to hostapd re-established\n");
1178 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1179 hostapd_cli_attached = 1;
1181 printf("Warning: Failed to attach to "
1187 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1188 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1192 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1198 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1200 char *argv[max_args];
1202 argc = tokenize_cmd(cmd, argv);
1204 wpa_request(ctrl_conn, argc, argv);
1208 static void hostapd_cli_edit_eof_cb(void *ctx)
1214 static void hostapd_cli_interactive(void)
1216 printf("\nInteractive mode\n\n");
1218 eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1219 edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1220 NULL, NULL, NULL, NULL);
1221 eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1225 edit_deinit(NULL, NULL);
1226 eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1230 static void hostapd_cli_cleanup(void)
1232 hostapd_cli_close_connection();
1234 os_daemonize_terminate(pid_file);
1236 os_program_deinit();
1240 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1248 fd = wpa_ctrl_get_fd(ctrl);
1250 while (!hostapd_cli_quit) {
1253 tv.tv_sec = ping_interval;
1255 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1256 if (res < 0 && errno != EINTR) {
1261 if (FD_ISSET(fd, &rfds))
1262 hostapd_cli_recv_pending(ctrl, 0, 1);
1264 len = sizeof(buf) - 1;
1265 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1266 hostapd_cli_action_process) < 0 ||
1267 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1268 printf("hostapd did not reply to PING "
1269 "command - exiting\n");
1277 int main(int argc, char *argv[])
1279 int warning_displayed = 0;
1283 if (os_program_init())
1287 c = getopt(argc, argv, "a:BhG:i:p:v");
1292 action_file = optarg;
1298 ping_interval = atoi(optarg);
1304 printf("%s\n", hostapd_cli_version);
1307 os_free(ctrl_ifname);
1308 ctrl_ifname = os_strdup(optarg);
1311 ctrl_iface_dir = optarg;
1319 interactive = (argc == optind) && (action_file == NULL);
1322 printf("%s\n\n%s\n\n", hostapd_cli_version,
1323 hostapd_cli_license);
1330 if (ctrl_ifname == NULL) {
1331 struct dirent *dent;
1332 DIR *dir = opendir(ctrl_iface_dir);
1334 while ((dent = readdir(dir))) {
1335 if (os_strcmp(dent->d_name, ".") == 0
1337 os_strcmp(dent->d_name, "..") == 0)
1339 printf("Selected interface '%s'\n",
1341 ctrl_ifname = os_strdup(dent->d_name);
1347 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1349 if (warning_displayed)
1350 printf("Connection established.\n");
1355 perror("Failed to connect to hostapd - "
1360 if (!warning_displayed) {
1361 printf("Could not connect to hostapd - re-trying\n");
1362 warning_displayed = 1;
1368 if (interactive || action_file) {
1369 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1370 hostapd_cli_attached = 1;
1372 printf("Warning: Failed to attach to hostapd.\n");
1378 if (daemonize && os_daemonize(pid_file))
1382 hostapd_cli_interactive();
1383 else if (action_file)
1384 hostapd_cli_action(ctrl_conn);
1386 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1388 os_free(ctrl_ifname);
1390 hostapd_cli_cleanup();