Add control interface commands for fetching wpa_config values
authorOla Olsson <ola1olsson@gmail.com>
Tue, 27 Jan 2015 23:22:06 +0000 (00:22 +0100)
committerJouni Malinen <j@w1.fi>
Sun, 8 Feb 2015 20:49:58 +0000 (22:49 +0200)
The new "DUMP" and "SET <variable>" control interface commands can be
used to fetch global wpa_supplicant configuration parameters.

Signed-off-by: Ola Olsson <ola.olsson@sonymobile.com>
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_cli.c

index 1ffc2dc..ea633a6 100644 (file)
@@ -3556,6 +3556,8 @@ struct global_parse_data {
        char *name;
        int (*parser)(const struct global_parse_data *data,
                      struct wpa_config *config, int line, const char *value);
+       int (*get)(const char *name, struct wpa_config *config, long offset,
+                  char *buf, size_t buflen, int pretty_print);
        void *param1, *param2, *param3;
        unsigned int changed_flag;
 };
@@ -4015,22 +4017,55 @@ static int wpa_config_process_no_ctrl_interface(
 #endif /* CONFIG_CTRL_IFACE */
 
 
+static int wpa_config_get_int(const char *name, struct wpa_config *config,
+                             long offset, char *buf, size_t buflen,
+                             int pretty_print)
+{
+       int *val = (int *) (((u8 *) config) + (long) offset);
+
+       if (pretty_print)
+               return os_snprintf(buf, buflen, "%s=%d\n", name, *val);
+       return os_snprintf(buf, buflen, "%d", *val);
+}
+
+
+static int wpa_config_get_str(const char *name, struct wpa_config *config,
+                             long offset, char *buf, size_t buflen,
+                             int pretty_print)
+{
+       char **val = (char **) (((u8 *) config) + (long) offset);
+       int res;
+
+       if (pretty_print)
+               res = os_snprintf(buf, buflen, "%s=%s\n", name,
+                                 *val ? *val : "null");
+       else if (!*val)
+               return -1;
+       else
+               res = os_snprintf(buf, buflen, "%s", *val);
+       if (os_snprintf_error(buflen, res))
+               res = -1;
+
+       return res;
+}
+
+
 #ifdef OFFSET
 #undef OFFSET
 #endif /* OFFSET */
 /* OFFSET: Get offset of a variable within the wpa_config structure */
 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
 
-#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
-#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
-#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
+#define FUNC(f) #f, wpa_config_process_ ## f, NULL, OFFSET(f), NULL, NULL
+#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL, NULL
+#define _INT(f) #f, wpa_global_config_parse_int, wpa_config_get_int, OFFSET(f)
 #define INT(f) _INT(f), NULL, NULL
 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
-#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
+#define _STR(f) #f, wpa_global_config_parse_str, wpa_config_get_str, OFFSET(f)
 #define STR(f) _STR(f), NULL, NULL
 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
-#define BIN(f) #f, wpa_global_config_parse_bin, OFFSET(f), NULL, NULL
-#define IPV4(f) #f, wpa_global_config_parse_ipv4, OFFSET(f), NULL, NULL
+#define BIN(f) #f, wpa_global_config_parse_bin, NULL, OFFSET(f), NULL, NULL
+#define IPV4(f) #f, wpa_global_config_parse_ipv4, NULL, OFFSET(f), NULL, NULL
 
 static const struct global_parse_data global_fields[] = {
 #ifdef CONFIG_CTRL_IFACE
@@ -4164,6 +4199,50 @@ static const struct global_parse_data global_fields[] = {
 #define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields)
 
 
+int wpa_config_dump_values(struct wpa_config *config, char *buf, size_t buflen)
+{
+       int result = 0;
+       size_t i;
+
+       for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
+               const struct global_parse_data *field = &global_fields[i];
+               int tmp;
+
+               if (!field->get)
+                       continue;
+
+               tmp = field->get(field->name, config, (long) field->param1,
+                                buf, buflen, 1);
+               if (tmp < 0)
+                       return -1;
+               buf += tmp;
+               buflen -= tmp;
+               result += tmp;
+       }
+       return result;
+}
+
+
+int wpa_config_get_value(const char *name, struct wpa_config *config,
+                        char *buf, size_t buflen)
+{
+       size_t i;
+
+       for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
+               const struct global_parse_data *field = &global_fields[i];
+
+               if (os_strcmp(name, field->name) != 0)
+                       continue;
+               if (!field->get)
+                       break;
+               return field->get(name, config, (long) field->param1,
+                                 buf, buflen, 0);
+       }
+
+       return -1;
+}
+
+
 int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
 {
        size_t i;
index 6adf1eb..2e54994 100644 (file)
@@ -1167,6 +1167,11 @@ int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
                   int line);
 int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
                          const char *value);
+int wpa_config_dump_values(struct wpa_config *config, char *buf,
+                          size_t buflen);
+int wpa_config_get_value(const char *name, struct wpa_config *config,
+                        char *buf, size_t buflen);
+
 char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys);
 char * wpa_config_get(struct wpa_ssid *ssid, const char *var);
 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var);
index 0162b6c..bbc6bd6 100644 (file)
@@ -498,6 +498,8 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_TESTING_GET_GTK */
        } else if (os_strcmp(cmd, "tls_library") == 0) {
                res = tls_get_library_version(buf, buflen);
+       } else {
+               res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
        }
 
        if (os_snprintf_error(buflen, res))
@@ -7838,6 +7840,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "SET ", 4) == 0) {
                if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
                        reply_len = -1;
+       } else if (os_strncmp(buf, "DUMP", 4) == 0) {
+               reply_len = wpa_config_dump_values(wpa_s->conf,
+                                                  reply, reply_size);
        } else if (os_strncmp(buf, "GET ", 4) == 0) {
                reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
                                                          reply, reply_size);
index af08e13..5a0af0d 100644 (file)
@@ -658,6 +658,11 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
        return NULL;
 }
 
+static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "DUMP");
+}
+
 
 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
@@ -2616,6 +2621,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
          cli_cmd_flag_none,
          "= set variables (shows list of variables when run without "
          "arguments)" },
+       { "dump", wpa_cli_cmd_dump, NULL,
+         cli_cmd_flag_none,
+         "= dump config variables" },
        { "get", wpa_cli_cmd_get, NULL,
          cli_cmd_flag_none,
          "<name> = get information" },