]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Global parser functions to return 1 when property unchanged
authorMatthew Wang <matthewmwang@chromium.org>
Thu, 16 Jul 2020 00:17:41 +0000 (17:17 -0700)
committerJouni Malinen <j@w1.fi>
Fri, 9 Oct 2020 13:50:36 +0000 (16:50 +0300)
Currently, wpa_config_set(), the function that sets wpa_supplicant
per-network properties, returns 1 when a property it attempts to set is
unchanged. Its global parallel, wpa_config_process_global(), doesn't do
this even though much of the code is very similar. Change this, and
several of the parser functions, to resemble the per-network parser and
setter functions.

Signed-off-by: Matthew Wang <matthewmwang@chromium.org>
src/utils/wpabuf.h
wpa_supplicant/config.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers.c

index 01da41b324d6688bc8565af8aca6ba42e14e2f95..b2a54b22fddb76cb898f75a764731fcdfe52f4f1 100644 (file)
@@ -70,6 +70,21 @@ static inline size_t wpabuf_tailroom(const struct wpabuf *buf)
        return buf->size - buf->used;
 }
 
+/**
+ * wpabuf_cmp - Check if two buffers contain the same data
+ * @a: wpabuf buffer
+ * @b: wpabuf buffer
+ * Returns: 0 if the two buffers contain the same data and non-zero otherwise
+ */
+static inline int wpabuf_cmp(const struct wpabuf *a, const struct wpabuf *b)
+{
+       if (!a && !b)
+               return 0;
+       if (a && b && wpabuf_size(a) == wpabuf_size(b))
+               return os_memcmp(a->buf, b->buf, wpabuf_size(a));
+       return -1;
+}
+
 /**
  * wpabuf_head - Get pointer to the head of the buffer data
  * @buf: wpabuf buffer
index 154687d3009653e56ef124f0aa44a3fd2bdfd865..0cbd09c863e2debedad18b2d37c5bdf425672905 100644 (file)
@@ -4360,13 +4360,31 @@ void wpa_config_debug_dump_networks(struct wpa_config *config)
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 
 
+/**
+ * Structure for global configuration parsing. This data is used to implement a
+ * generic parser for the global interface configuration. The table of variables
+ * is defined below in this file (global_fields[]).
+ */
 struct global_parse_data {
+       /* Configuration variable name */
        char *name;
+
+       /* Parser function for this variable. The parser functions return 0 or 1
+        * to indicate success. Value 0 indicates that the parameter value may
+        * have changed while value 1 means that the value did not change.
+        * Error cases (failure to parse the string) are indicated by returning
+        * -1. */
        int (*parser)(const struct global_parse_data *data,
                      struct wpa_config *config, int line, const char *value);
+
+       /* Getter function to print the variable in text format to buf. */
        int (*get)(const char *name, struct wpa_config *config, long offset,
                   char *buf, size_t buflen, int pretty_print);
+
+       /* Variable specific parameters for the parser. */
        void *param1, *param2, *param3;
+
+       /* Indicates which configuration variable has changed. */
        unsigned int changed_flag;
 };
 
@@ -4377,6 +4395,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data,
 {
        int val, *dst;
        char *end;
+       bool same;
 
        dst = (int *) (((u8 *) config) + (long) data->param1);
        val = strtol(pos, &end, 0);
@@ -4385,6 +4404,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data,
                           line, pos);
                return -1;
        }
+       same = *dst == val;
        *dst = val;
 
        wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
@@ -4405,7 +4425,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data,
                return -1;
        }
 
-       return 0;
+       return same;
 }
 
 
@@ -4413,7 +4433,7 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data,
                                       struct wpa_config *config, int line,
                                       const char *pos)
 {
-       size_t len;
+       size_t len, prev_len;
        char **dst, *tmp;
 
        len = os_strlen(pos);
@@ -4437,11 +4457,22 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data,
                return -1;
        }
 
+       dst = (char **) (((u8 *) config) + (long) data->param1);
+       if (*dst)
+               prev_len = os_strlen(*dst);
+       else
+               prev_len = 0;
+
+       /* No change to the previously configured value */
+       if ((!(*dst) && !pos) ||
+           (*dst && pos && prev_len == len &&
+            os_memcmp(*dst, pos, len) == 0))
+               return 1;
+
        tmp = os_strdup(pos);
        if (tmp == NULL)
                return -1;
 
-       dst = (char **) (((u8 *) config) + (long) data->param1);
        os_free(*dst);
        *dst = tmp;
        wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
@@ -4482,6 +4513,10 @@ static int wpa_global_config_parse_bin(const struct global_parse_data *data,
                return -1;
 
        dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1);
+       if (wpabuf_cmp(*dst, tmp) == 0) {
+               wpabuf_free(tmp);
+               return 1;
+       }
        wpabuf_free(*dst);
        *dst = tmp;
        wpa_printf(MSG_DEBUG, "%s", data->name);
@@ -4523,6 +4558,8 @@ static int wpa_global_config_parse_ipv4(const struct global_parse_data *data,
                return -1;
 
        dst = (u32 *) (((u8 *) config) + (long) data->param1);
+       if (os_memcmp(dst, &addr.u.v4.s_addr, 4) == 0)
+               return 1;
        os_memcpy(dst, &addr.u.v4.s_addr, 4);
        wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name,
                   WPA_GET_BE32((u8 *) dst));
@@ -4540,6 +4577,8 @@ static int wpa_config_process_country(const struct global_parse_data *data,
                wpa_printf(MSG_DEBUG, "Invalid country set");
                return -1;
        }
+       if (pos[0] == config->country[0] && pos[1] == config->country[1])
+               return 1;
        config->country[0] = pos[0];
        config->country[1] = pos[1];
        wpa_printf(MSG_DEBUG, "country='%c%c'",
@@ -5159,6 +5198,19 @@ const char * wpa_config_get_global_field_name(unsigned int i, int *no_var)
 }
 
 
+/**
+ * wpa_config_process_global - Set a variable in global configuration
+ * @config: Pointer to global configuration data
+ * @pos: Name and value in the format "{name}={value}"
+ * @line: Line number in configuration file or 0 if not used
+ * Returns: 0 on success with a possible change in value, 1 on success with no
+ * change to previously configured value, or -1 on failure
+ *
+ * This function can be used to set global configuration variables based on
+ * both the configuration file and management interface input. The value
+ * parameter must be in the same format as the text-based configuration file is
+ * using. For example, strings are using double quotation marks.
+ */
 int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
 {
        size_t i;
@@ -5171,11 +5223,14 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
                    pos[flen] != '=')
                        continue;
 
-               if (field->parser(field, config, line, pos + flen + 1)) {
+               ret = field->parser(field, config, line, pos + flen + 1);
+               if (ret < 0) {
                        wpa_printf(MSG_ERROR, "Line %d: failed to "
                                   "parse '%s'.", line, pos);
                        ret = -1;
                }
+               if (ret == 1)
+                       break;
                if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN)
                        config->wps_nfc_pw_from_config = 1;
                config->changed_parameters |= field->changed_flag;
index 5048ee83efff036ccb5a9f1fbe991da41c478a2e..127b5fe0bcdce90dce6354db00ac0ce360e274fc 100644 (file)
@@ -898,6 +898,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
                if (ret == 0)
                        wpa_supplicant_update_config(wpa_s);
+               else if (ret == 1)
+                       ret = 0;
        }
 
        return ret;
index 1c3f333678ed5f1143212b18259f93de38ba92d8..defb9d405642180d7d834eab13bc96f55d603068 100644 (file)
@@ -3983,14 +3983,15 @@ dbus_bool_t wpas_dbus_setter_iface_global(
                return FALSE;
        }
 
-       if (wpa_config_process_global(wpa_s->conf, buf, -1)) {
+       ret = wpa_config_process_global(wpa_s->conf, buf, -1);
+       if (ret < 0) {
                dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
                               "Failed to set interface property %s",
                               property_desc->dbus_property);
                return FALSE;
+       } else if (ret == 0) {
+               wpa_supplicant_update_config(wpa_s);
        }
-
-       wpa_supplicant_update_config(wpa_s);
        return TRUE;
 }