hostapd: Add support to configure debug log level at runtime
[mech_eap.git] / hostapd / hostapd_cli.c
index c488b4f..9ca50be 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd - command line interface for hostapd daemon
- * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
  *
  * 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 "common/ieee802_11_defs.h"
 #include "utils/common.h"
 #include "utils/eloop.h"
 #include "utils/edit.h"
 #include "common/version.h"
 
 
-static const char *hostapd_cli_version =
+static const char *const hostapd_cli_version =
 "hostapd_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2015, 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";
 
-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"
@@ -56,7 +57,7 @@ static const char *hostapd_cli_full_license =
 "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"
@@ -111,7 +112,7 @@ static void usage(void)
                "\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"
@@ -238,28 +239,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)
 {
-       char *cmd;
+       char *arg;
        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)
+       len = os_strlen(arg1) + os_strlen(arg2) + 2;
+       arg = os_malloc(len);
+       if (arg == NULL)
                return -1;
-       res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
-       if (res < 0 || (size_t) res >= len) {
-               os_free(cmd);
-               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;
 }
 
 
@@ -402,7 +394,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]);
-       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;
        }
@@ -465,7 +457,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]);
-       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;
        }
@@ -486,7 +478,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]);
-       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;
        }
@@ -508,7 +500,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]);
-       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;
        }
@@ -550,7 +542,7 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
                                      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;
 
@@ -561,7 +553,7 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
        }
 
        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]);
@@ -605,7 +597,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]);
-       if (res < 0 || res >= (int) sizeof(buf))
+       if (os_snprintf_error(sizeof(buf), res))
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
@@ -625,8 +617,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]);
-       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;
+       }
+
+       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);
 }
 
@@ -718,7 +737,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]);
-       if (res < 0 || res >= (int) sizeof(buf))
+       if (os_snprintf_error(sizeof(buf), res))
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
@@ -737,7 +756,7 @@ 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]);
-       if (res < 0 || res >= (int) sizeof(buf))
+       if (os_snprintf_error(sizeof(buf), res))
                return -1;
        return wpa_ctrl_command(ctrl, buf);
 }
@@ -757,7 +776,7 @@ static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
 
        res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %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);
 }
@@ -782,7 +801,7 @@ static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
                res = os_snprintf(buf, sizeof(buf),
                                  "HS20_DEAUTH_REQ %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);
 }
@@ -842,8 +861,10 @@ static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
        }
 
        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);
@@ -873,7 +894,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]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long SET command.\n");
                return -1;
        }
@@ -893,7 +914,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]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long GET command.\n");
                return -1;
        }
@@ -901,6 +922,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[])
 {
@@ -921,7 +971,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]);
-       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;
        }
@@ -930,7 +980,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]);
-               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;
                }
@@ -940,6 +990,27 @@ 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];
@@ -953,7 +1024,7 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
 
        res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
                          argc == 3 ? argv[2] : "");
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long VENDOR command.\n");
                return -1;
        }
@@ -961,12 +1032,38 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
+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);
+}
+
+
 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 },
@@ -996,9 +1093,13 @@ 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 },
+       { "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 },
+#ifdef CONFIG_FST
+       { "fst", hostapd_cli_cmd_fst },
+#endif /* CONFIG_FST */
        { "level", hostapd_cli_cmd_level },
        { "license", hostapd_cli_cmd_license },
        { "quit", hostapd_cli_cmd_quit },
@@ -1010,13 +1111,18 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
        { "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 },
        { 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;
@@ -1231,7 +1337,7 @@ int main(int argc, char *argv[])
                return -1;
 
        for (;;) {
-               c = getopt(argc, argv, "a:BhG:i:p:v");
+               c = getopt(argc, argv, "a:BhG:i:p:P:v");
                if (c < 0)
                        break;
                switch (c) {
@@ -1257,6 +1363,9 @@ int main(int argc, char *argv[])
                case 'p':
                        ctrl_iface_dir = optarg;
                        break;
+               case 'P':
+                       pid_file = optarg;
+                       break;
                default:
                        usage();
                        return -1;