/* Configuration variable name */
char *name;
- /* Parser function for this variable */
+ /* 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 parse_data *data, struct wpa_ssid *ssid,
int line, const char *value);
struct wpa_ssid *ssid,
int line, const char *value)
{
- size_t res_len, *dst_len;
+ size_t res_len, *dst_len, prev_len;
char **dst, *tmp;
if (os_strcmp(value, "NULL") == 0) {
set:
dst = (char **) (((u8 *) ssid) + (long) data->param1);
dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
+
+ if (data->param2)
+ prev_len = *dst_len;
+ else if (*dst)
+ prev_len = os_strlen(*dst);
+ else
+ prev_len = 0;
+ if ((*dst == NULL && tmp == NULL) ||
+ (*dst && tmp && prev_len == res_len &&
+ os_memcmp(*dst, tmp, res_len) == 0)) {
+ /* No change to the previously configured value */
+ os_free(tmp);
+ return 1;
+ }
+
os_free(*dst);
*dst = tmp;
if (data->param2)
line, value);
return -1;
}
+
+ if (*dst == val)
+ return 1;
*dst = val;
wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
(u8 *) value, len);
if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
- os_memcmp(ssid->passphrase, value, len) == 0)
- return 0;
+ os_memcmp(ssid->passphrase, value, len) == 0) {
+ /* No change to the previously configured value */
+ return 1;
+ }
ssid->psk_set = 0;
str_clear_free(ssid->passphrase);
ssid->passphrase = dup_binstr(value, len);
errors++;
}
+ if (!errors && ssid->proto == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
ssid->proto = val;
return errors ? -1 : 0;
errors++;
}
+ if (!errors && ssid->key_mgmt == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
ssid->key_mgmt = val;
return errors ? -1 : 0;
return -1;
}
+ if (ssid->pairwise_cipher == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
ssid->pairwise_cipher = val;
return 0;
return -1;
}
+ if (ssid->group_cipher == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
ssid->group_cipher = val;
return 0;
errors++;
}
+ if (!errors && ssid->auth_alg == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
ssid->auth_alg = val;
return errors ? -1 : 0;
methods[num_methods].method = EAP_TYPE_NONE;
num_methods++;
+ if (!errors && ssid->eap.eap_methods) {
+ struct eap_method_type *prev_m;
+ size_t i, j, prev_methods, match = 0;
+
+ prev_m = ssid->eap.eap_methods;
+ for (i = 0; prev_m[i].vendor != EAP_VENDOR_IETF ||
+ prev_m[i].method != EAP_TYPE_NONE; i++) {
+ /* Count the methods */
+ }
+ prev_methods = i + 1;
+
+ for (i = 0; prev_methods == num_methods && i < prev_methods;
+ i++) {
+ for (j = 0; j < num_methods; j++) {
+ if (prev_m[i].vendor == methods[j].vendor &&
+ prev_m[i].method == methods[j].method) {
+ match++;
+ break;
+ }
+ }
+ }
+ if (match == num_methods) {
+ os_free(methods);
+ return 1;
+ }
+ }
wpa_hexdump(MSG_MSGDUMP, "eap methods",
(u8 *) methods, num_methods * sizeof(*methods));
os_free(ssid->eap.eap_methods);
u8 *hash;
if (os_strcmp(value, "NULL") == 0) {
+ if (!ssid->eap.password)
+ return 1; /* Already unset */
wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
bin_clear_free(ssid->eap.password, ssid->eap.password_len);
ssid->eap.password = NULL;
wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
+ if (ssid->eap.password && ssid->eap.password_len == 16 &&
+ os_memcmp(ssid->eap.password, hash, 16) == 0 &&
+ (ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
+ bin_clear_free(hash, 16);
+ return 1;
+ }
bin_clear_free(ssid->eap.password, ssid->eap.password_len);
ssid->eap.password = hash;
ssid->eap.password_len = 16;
* @var: Variable name, e.g., "ssid"
* @value: Variable value
* @line: Line number in configuration file or 0 if not used
- * Returns: 0 on success, -1 on failure
+ * Returns: 0 on success with possible change in the value, 1 on success with
+ * no change to previously configured value, or -1 on failure
*
* This function can be used to set network configuration variables based on
* both the configuration file and management interface input. The value
if (os_strcmp(var, field->name) != 0)
continue;
- if (field->parser(field, ssid, line, value)) {
+ ret = field->parser(field, ssid, line, value);
+ if (ret < 0) {
if (line) {
wpa_printf(MSG_ERROR, "Line %d: failed to "
"parse %s '%s'.", line, var, value);