Make driver flags available through control interface
[mech_eap.git] / hostapd / hostapd_cli.c
index b2d3e5b..5c1f297 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd - command line interface for hostapd daemon
 /*
  * hostapd - command line interface for hostapd daemon
- * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
 #include <dirent.h>
 
 #include "common/wpa_ctrl.h"
 #include <dirent.h>
 
 #include "common/wpa_ctrl.h"
+#include "common/ieee802_11_defs.h"
 #include "utils/common.h"
 #include "utils/eloop.h"
 #include "utils/edit.h"
 #include "common/version.h"
 
 #include "utils/common.h"
 #include "utils/eloop.h"
 #include "utils/edit.h"
 #include "common/version.h"
 
+#ifndef CONFIG_NO_CTRL_IFACE
 
 
-static const char *hostapd_cli_version =
+static const char *const hostapd_cli_version =
 "hostapd_cli v" VERSION_STR "\n"
 "hostapd_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
 
 
 
 
-static const char *hostapd_cli_license =
+static const char *const hostapd_cli_license =
 "This software may be distributed under the terms of the BSD license.\n"
 "See README for more details.\n";
 
 "This software may be distributed under the terms of the BSD license.\n"
 "See README for more details.\n";
 
-static const char *hostapd_cli_full_license =
+static const char *const hostapd_cli_full_license =
 "This software may be distributed under the terms of the BSD license.\n"
 "\n"
 "Redistribution and use in source and binary forms, with or without\n"
 "This software may be distributed under the terms of the BSD license.\n"
 "\n"
 "Redistribution and use in source and binary forms, with or without\n"
@@ -56,7 +58,7 @@ static const char *hostapd_cli_full_license =
 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
 "\n";
 
 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
 "\n";
 
-static const char *commands_help =
+static const char *const commands_help =
 "Commands:\n"
 "   mib                  get MIB variables (dot1x, dot11, radius)\n"
 "   sta <addr>           get MIB variables for one station\n"
 "Commands:\n"
 "   mib                  get MIB variables (dot1x, dot11, radius)\n"
 "   sta <addr>           get MIB variables for one station\n"
@@ -96,6 +98,7 @@ static int hostapd_cli_attached = 0;
 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
 #endif /* CONFIG_CTRL_IFACE_DIR */
 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
 #endif /* CONFIG_CTRL_IFACE_DIR */
 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
+static const char *client_socket_dir = NULL;
 
 static char *ctrl_ifname = NULL;
 static const char *pid_file = NULL;
 
 static char *ctrl_ifname = NULL;
 static const char *pid_file = NULL;
@@ -111,13 +114,15 @@ static void usage(void)
                "\n"
                "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
                "[-a<path>] \\\n"
                "\n"
                "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
                "[-a<path>] \\\n"
-               "                   [-G<ping interval>] [command..]\n"
+               "                   [-P<pid file>] [-G<ping interval>] [command..]\n"
                "\n"
                "Options:\n"
                "   -h           help (show this usage text)\n"
                "   -v           shown version information\n"
                "   -p<path>     path to find control sockets (default: "
                "/var/run/hostapd)\n"
                "\n"
                "Options:\n"
                "   -h           help (show this usage text)\n"
                "   -v           shown version information\n"
                "   -p<path>     path to find control sockets (default: "
                "/var/run/hostapd)\n"
+               "   -s<dir_path> dir path to open client sockets (default: "
+               CONFIG_CTRL_IFACE_DIR ")\n"
                "   -a<file>     run in daemon mode executing the action file "
                "based on events\n"
                "                from hostapd\n"
                "   -a<file>     run in daemon mode executing the action file "
                "based on events\n"
                "                from hostapd\n"
@@ -132,21 +137,35 @@ static void usage(void)
 
 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
 {
 
 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
 {
+#ifndef CONFIG_CTRL_IFACE_UDP
        char *cfile;
        int flen;
        char *cfile;
        int flen;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
 
        if (ifname == NULL)
                return NULL;
 
 
        if (ifname == NULL)
                return NULL;
 
+#ifdef CONFIG_CTRL_IFACE_UDP
+       ctrl_conn = wpa_ctrl_open(ifname);
+       return ctrl_conn;
+#else /* CONFIG_CTRL_IFACE_UDP */
        flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
        cfile = malloc(flen);
        if (cfile == NULL)
                return NULL;
        snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
 
        flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
        cfile = malloc(flen);
        if (cfile == NULL)
                return NULL;
        snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
 
-       ctrl_conn = wpa_ctrl_open(cfile);
+       if (client_socket_dir && client_socket_dir[0] &&
+           access(client_socket_dir, F_OK) < 0) {
+               perror(client_socket_dir);
+               free(cfile);
+               return NULL;
+       }
+
+       ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
        free(cfile);
        return ctrl_conn;
        free(cfile);
        return ctrl_conn;
+#endif /* CONFIG_CTRL_IFACE_UDP */
 }
 
 
 }
 
 
@@ -204,6 +223,52 @@ static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
 }
 
 
 }
 
 
+static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
+                    char *argv[])
+{
+       int i, res;
+       char *pos, *end;
+
+       pos = buf;
+       end = buf + buflen;
+
+       res = os_snprintf(pos, end - pos, "%s", cmd);
+       if (os_snprintf_error(end - pos, res))
+               goto fail;
+       pos += res;
+
+       for (i = 0; i < argc; i++) {
+               res = os_snprintf(pos, end - pos, " %s", argv[i]);
+               if (os_snprintf_error(end - pos, res))
+                       goto fail;
+               pos += res;
+       }
+
+       buf[buflen - 1] = '\0';
+       return 0;
+
+fail:
+       printf("Too long command\n");
+       return -1;
+}
+
+
+static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
+                          int min_args, int argc, char *argv[])
+{
+       char buf[4096];
+
+       if (argc < min_args) {
+               printf("Invalid %s command - at least %d argument%s required.\n",
+                      cmd, min_args, min_args > 1 ? "s are" : " is");
+               return -1;
+       }
+       if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
+               return -1;
+       return wpa_ctrl_command(ctrl, buf);
+}
+
+
 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        return wpa_ctrl_command(ctrl, "PING");
 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        return wpa_ctrl_command(ctrl, "PING");
@@ -218,12 +283,19 @@ static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
 
 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 
 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
+       if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
+               return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
        return wpa_ctrl_command(ctrl, "STATUS");
 }
 
 
 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        return wpa_ctrl_command(ctrl, "STATUS");
 }
 
 
 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
+       if (argc > 0) {
+               char buf[100];
+               os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
+               return wpa_ctrl_command(ctrl, buf);
+       }
        return wpa_ctrl_command(ctrl, "MIB");
 }
 
        return wpa_ctrl_command(ctrl, "MIB");
 }
 
@@ -231,28 +303,19 @@ static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
 static int hostapd_cli_exec(const char *program, const char *arg1,
                            const char *arg2)
 {
 static int hostapd_cli_exec(const char *program, const char *arg1,
                            const char *arg2)
 {
-       char *cmd;
+       char *arg;
        size_t len;
        int res;
        size_t len;
        int res;
-       int ret = 0;
 
 
-       len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
-       cmd = os_malloc(len);
-       if (cmd == NULL)
-               return -1;
-       res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
-       if (res < 0 || (size_t) res >= len) {
-               os_free(cmd);
+       len = os_strlen(arg1) + os_strlen(arg2) + 2;
+       arg = os_malloc(len);
+       if (arg == NULL)
                return -1;
                return -1;
-       }
-       cmd[len - 1] = '\0';
-#ifndef _WIN32_WCE
-       if (system(cmd) < 0)
-               ret = -1;
-#endif /* _WIN32_WCE */
-       os_free(cmd);
+       os_snprintf(arg, len, "%s %s", arg1, arg2);
+       res = os_exec(program, arg, 1);
+       os_free(arg);
 
 
-       return ret;
+       return res;
 }
 
 
 }
 
 
@@ -276,12 +339,15 @@ static void hostapd_cli_action_process(char *msg, size_t len)
 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        char buf[64];
 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        char buf[64];
-       if (argc != 1) {
-               printf("Invalid 'sta' command - exactly one argument, STA "
+       if (argc < 1) {
+               printf("Invalid 'sta' command - at least one argument, STA "
                       "address, is required.\n");
                return -1;
        }
                       "address, is required.\n");
                return -1;
        }
-       snprintf(buf, sizeof(buf), "STA %s", argv[0]);
+       if (argc > 1)
+               snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
+       else
+               snprintf(buf, sizeof(buf), "STA %s", argv[0]);
        return wpa_ctrl_command(ctrl, buf);
 }
 
        return wpa_ctrl_command(ctrl, buf);
 }
 
@@ -392,7 +458,7 @@ static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
        else
                res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
                                  argv[0]);
        else
                res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
                                  argv[0]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long WPS_CHECK_PIN command.\n");
                return -1;
        }
                printf("Too long WPS_CHECK_PIN command.\n");
                return -1;
        }
@@ -455,7 +521,7 @@ static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
 
        res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
                          argv[0]);
 
        res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
                          argv[0]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
                return -1;
        }
                printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
                return -1;
        }
@@ -476,7 +542,7 @@ static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
        }
 
        res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
        }
 
        res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long WPS_NFC_TOKEN command.\n");
                return -1;
        }
                printf("Too long WPS_NFC_TOKEN command.\n");
                return -1;
        }
@@ -498,7 +564,7 @@ static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
 
        res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
                          argv[0], argv[1]);
 
        res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
                          argv[0], argv[1]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long NFC_GET_HANDOVER_SEL command.\n");
                return -1;
        }
                printf("Too long NFC_GET_HANDOVER_SEL command.\n");
                return -1;
        }
@@ -540,7 +606,7 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
                                      char *argv[])
 {
        char buf[256];
                                      char *argv[])
 {
        char buf[256];
-       char ssid_hex[2 * 32 + 1];
+       char ssid_hex[2 * SSID_MAX_LEN + 1];
        char key_hex[2 * 64 + 1];
        int i;
 
        char key_hex[2 * 64 + 1];
        int i;
 
@@ -551,7 +617,7 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
        }
 
        ssid_hex[0] = '\0';
        }
 
        ssid_hex[0] = '\0';
-       for (i = 0; i < 32; i++) {
+       for (i = 0; i < SSID_MAX_LEN; i++) {
                if (argv[0][i] == '\0')
                        break;
                os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
                if (argv[0][i] == '\0')
                        break;
                os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
@@ -595,7 +661,7 @@ static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
 
        res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
                          argv[0], argv[1]);
 
        res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
                          argv[0], argv[1]);
-       if (res < 0 || res >= (int) sizeof(buf))
+       if (os_snprintf_error(sizeof(buf), res))
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
@@ -615,8 +681,35 @@ static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
 
        res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
                          argv[0], argv[1], argv[2]);
 
        res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
                          argv[0], argv[1], argv[2]);
-       if (res < 0 || res >= (int) sizeof(buf))
+       if (os_snprintf_error(sizeof(buf), res))
+               return -1;
+       return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
+                                     char *argv[])
+{
+       char buf[2000], *tmp;
+       int res, i, total;
+
+       if (argc < 1) {
+               printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
                return -1;
                return -1;
+       }
+
+       res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
+       if (os_snprintf_error(sizeof(buf), res))
+               return -1;
+
+       total = res;
+       for (i = 1; i < argc; i++) {
+               tmp = &buf[total];
+               res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
+               if (os_snprintf_error(sizeof(buf) - total, res))
+                       return -1;
+               total += res;
+       }
        return wpa_ctrl_command(ctrl, buf);
 }
 
        return wpa_ctrl_command(ctrl, buf);
 }
 
@@ -708,7 +801,7 @@ static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
        }
 
        res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
        }
 
        res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
-       if (res < 0 || res >= (int) sizeof(buf))
+       if (os_snprintf_error(sizeof(buf), res))
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
@@ -727,7 +820,52 @@ static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
        }
 
        res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
        }
 
        res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
-       if (res < 0 || res >= (int) sizeof(buf))
+       if (os_snprintf_error(sizeof(buf), res))
+               return -1;
+       return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
+                                         char *argv[])
+{
+       char buf[300];
+       int res;
+
+       if (argc < 2) {
+               printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
+                      "addr and URL) are needed\n");
+               return -1;
+       }
+
+       res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
+                         argv[0], argv[1]);
+       if (os_snprintf_error(sizeof(buf), res))
+               return -1;
+       return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
+                                          char *argv[])
+{
+       char buf[300];
+       int res;
+
+       if (argc < 3) {
+               printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
+               return -1;
+       }
+
+       if (argc > 3)
+               res = os_snprintf(buf, sizeof(buf),
+                                 "HS20_DEAUTH_REQ %s %s %s %s",
+                                 argv[0], argv[1], argv[2], argv[3]);
+       else
+               res = os_snprintf(buf, sizeof(buf),
+                                 "HS20_DEAUTH_REQ %s %s %s",
+                                 argv[0], argv[1], argv[2]);
+       if (os_snprintf_error(sizeof(buf), res))
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
@@ -787,8 +925,10 @@ static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
        }
 
        hostapd_cli_close_connection();
        }
 
        hostapd_cli_close_connection();
-       free(ctrl_ifname);
-       ctrl_ifname = strdup(argv[0]);
+       os_free(ctrl_ifname);
+       ctrl_ifname = os_strdup(argv[0]);
+       if (ctrl_ifname == NULL)
+               return -1;
 
        if (hostapd_cli_open_connection(ctrl_ifname)) {
                printf("Connected to interface '%s.\n", ctrl_ifname);
 
        if (hostapd_cli_open_connection(ctrl_ifname)) {
                printf("Connected to interface '%s.\n", ctrl_ifname);
@@ -818,7 +958,7 @@ static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
        }
 
        res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
        }
 
        res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long SET command.\n");
                return -1;
        }
                printf("Too long SET command.\n");
                return -1;
        }
@@ -838,7 +978,7 @@ static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
        }
 
        res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
        }
 
        res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long GET command.\n");
                return -1;
        }
                printf("Too long GET command.\n");
                return -1;
        }
@@ -846,6 +986,35 @@ static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
 }
 
 
+#ifdef CONFIG_FST
+static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       char cmd[256];
+       int res;
+       int i;
+       int total;
+
+       if (argc <= 0) {
+               printf("FST command: parameters are required.\n");
+               return -1;
+       }
+
+       total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
+
+       for (i = 0; i < argc; i++) {
+               res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
+                                 argv[i]);
+               if (os_snprintf_error(sizeof(cmd) - total, res)) {
+                       printf("Too long fst command.\n");
+                       return -1;
+               }
+               total += res;
+       }
+       return wpa_ctrl_command(ctrl, cmd);
+}
+#endif /* CONFIG_FST */
+
+
 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
                                       int argc, char *argv[])
 {
 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
                                       int argc, char *argv[])
 {
@@ -866,7 +1035,7 @@ static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
 
        res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
                          argv[0], argv[1]);
 
        res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
                          argv[0], argv[1]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long CHAN_SWITCH command.\n");
                return -1;
        }
                printf("Too long CHAN_SWITCH command.\n");
                return -1;
        }
@@ -875,7 +1044,7 @@ static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
        for (i = 2; i < argc; i++) {
                tmp = cmd + total;
                res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
        for (i = 2; i < argc; i++) {
                tmp = cmd + total;
                res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
-               if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) {
+               if (os_snprintf_error(sizeof(cmd) - total, res)) {
                        printf("Too long CHAN_SWITCH command.\n");
                        return -1;
                }
                        printf("Too long CHAN_SWITCH command.\n");
                        return -1;
                }
@@ -885,12 +1054,183 @@ static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
 }
 
 
 }
 
 
+static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
+                                     char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "ENABLE");
+}
+
+
+static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
+                                     char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "RELOAD");
+}
+
+
+static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
+                                     char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "DISABLE");
+}
+
+
+static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       char cmd[256];
+       int res;
+
+       if (argc < 2 || argc > 3) {
+               printf("Invalid vendor command\n"
+                      "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
+               return -1;
+       }
+
+       res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
+                         argc == 3 ? argv[2] : "");
+       if (os_snprintf_error(sizeof(cmd), res)) {
+               printf("Too long VENDOR command.\n");
+               return -1;
+       }
+       return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
+                                    char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "ERP_FLUSH");
+}
+
+
+static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
+                                    char *argv[])
+{
+       char cmd[256];
+       int res;
+
+       res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
+                         argc >= 1 ? " " : "",
+                         argc >= 1 ? argv[0] : "",
+                         argc == 2 ? " " : "",
+                         argc == 2 ? argv[1] : "");
+       if (os_snprintf_error(sizeof(cmd), res)) {
+               printf("Too long option\n");
+               return -1;
+       }
+       return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       if (argc == 0)
+               return -1;
+       return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
+}
+
+
+static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "PMKSA");
+}
+
+
+static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
+                                      char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
+}
+
+
+static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
+                                       char *argv[])
+{
+       char cmd[2048];
+       int res;
+
+       if (argc < 3 || argc > 5) {
+               printf("Invalid set_neighbor command: needs 3-5 arguments\n");
+               return -1;
+       }
+
+       res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
+                         argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
+                         argc == 5 ? argv[4] : "");
+       if (os_snprintf_error(sizeof(cmd), res)) {
+               printf("Too long SET_NEIGHBOR command.\n");
+               return -1;
+       }
+       return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
+                                          char *argv[])
+{
+       char cmd[400];
+       int res;
+
+       if (argc != 2) {
+               printf("Invalid remove_neighbor command: needs 2 arguments\n");
+               return -1;
+       }
+
+       res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
+                         argv[0], argv[1]);
+       if (os_snprintf_error(sizeof(cmd), res)) {
+               printf("Too long REMOVE_NEIGHBOR command.\n");
+               return -1;
+       }
+       return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
+                                  char *argv[])
+{
+       char cmd[256];
+       int res;
+
+       if (argc != 1) {
+               printf("Invalid req_lci command - requires destination address\n");
+               return -1;
+       }
+
+       res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
+       if (os_snprintf_error(sizeof(cmd), res)) {
+               printf("Too long REQ_LCI command.\n");
+               return -1;
+       }
+       return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
+                                    char *argv[])
+{
+       if (argc < 4) {
+               printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
+               return -1;
+       }
+
+       return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
+}
+
+
+static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
+                                       char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
+}
+
+
 struct hostapd_cli_cmd {
        const char *cmd;
        int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
 };
 
 struct hostapd_cli_cmd {
        const char *cmd;
        int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
 };
 
-static struct hostapd_cli_cmd hostapd_cli_commands[] = {
+static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
        { "ping", hostapd_cli_cmd_ping },
        { "mib", hostapd_cli_cmd_mib },
        { "relog", hostapd_cli_cmd_relog },
        { "ping", hostapd_cli_cmd_ping },
        { "mib", hostapd_cli_cmd_mib },
        { "relog", hostapd_cli_cmd_relog },
@@ -920,9 +1260,14 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
 #endif /* CONFIG_WPS */
        { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
        { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
 #endif /* CONFIG_WPS */
        { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
        { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
+       { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
        { "get_config", hostapd_cli_cmd_get_config },
        { "help", hostapd_cli_cmd_help },
        { "interface", hostapd_cli_cmd_interface },
        { "get_config", hostapd_cli_cmd_get_config },
        { "help", hostapd_cli_cmd_help },
        { "interface", hostapd_cli_cmd_interface },
+#ifdef CONFIG_FST
+       { "fst", hostapd_cli_cmd_fst },
+#endif /* CONFIG_FST */
+       { "raw", hostapd_cli_cmd_raw },
        { "level", hostapd_cli_cmd_level },
        { "license", hostapd_cli_cmd_license },
        { "quit", hostapd_cli_cmd_quit },
        { "level", hostapd_cli_cmd_level },
        { "license", hostapd_cli_cmd_license },
        { "quit", hostapd_cli_cmd_quit },
@@ -931,13 +1276,28 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
        { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
        { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
        { "chan_switch", hostapd_cli_cmd_chan_switch },
        { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
        { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
        { "chan_switch", hostapd_cli_cmd_chan_switch },
+       { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
+       { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
+       { "vendor", hostapd_cli_cmd_vendor },
+       { "enable", hostapd_cli_cmd_enable },
+       { "reload", hostapd_cli_cmd_reload },
+       { "disable", hostapd_cli_cmd_disable },
+       { "erp_flush", hostapd_cli_cmd_erp_flush },
+       { "log_level", hostapd_cli_cmd_log_level },
+       { "pmksa", hostapd_cli_cmd_pmksa },
+       { "pmksa_flush", hostapd_cli_cmd_pmksa_flush },
+       { "set_neighbor", hostapd_cli_cmd_set_neighbor },
+       { "remove_neighbor", hostapd_cli_cmd_remove_neighbor },
+       { "req_lci", hostapd_cli_cmd_req_lci },
+       { "req_range", hostapd_cli_cmd_req_range },
+       { "driver_flags", hostapd_cli_cmd_driver_flags },
        { NULL, NULL }
 };
 
 
 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        { NULL, NULL }
 };
 
 
 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
-       struct hostapd_cli_cmd *cmd, *match = NULL;
+       const struct hostapd_cli_cmd *cmd, *match = NULL;
        int count;
 
        count = 0;
        int count;
 
        count = 0;
@@ -1152,7 +1512,7 @@ int main(int argc, char *argv[])
                return -1;
 
        for (;;) {
                return -1;
 
        for (;;) {
-               c = getopt(argc, argv, "a:BhG:i:p:v");
+               c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
                if (c < 0)
                        break;
                switch (c) {
                if (c < 0)
                        break;
                switch (c) {
@@ -1178,6 +1538,12 @@ int main(int argc, char *argv[])
                case 'p':
                        ctrl_iface_dir = optarg;
                        break;
                case 'p':
                        ctrl_iface_dir = optarg;
                        break;
+               case 'P':
+                       pid_file = optarg;
+                       break;
+               case 's':
+                       client_socket_dir = optarg;
+                       break;
                default:
                        usage();
                        return -1;
                default:
                        usage();
                        return -1;
@@ -1243,7 +1609,7 @@ int main(int argc, char *argv[])
                }
        }
 
                }
        }
 
-       if (daemonize && os_daemonize(pid_file))
+       if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
                return -1;
 
        if (interactive)
                return -1;
 
        if (interactive)
@@ -1258,3 +1624,12 @@ int main(int argc, char *argv[])
        hostapd_cli_cleanup();
        return 0;
 }
        hostapd_cli_cleanup();
        return 0;
 }
+
+#else /* CONFIG_NO_CTRL_IFACE */
+
+int main(int argc, char *argv[])
+{
+       return -1;
+}
+
+#endif /* CONFIG_NO_CTRL_IFACE */