X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=wpa_supplicant%2Fconfig.c;h=ce631dd7e87bd6e0e327398c76df9d43b7e96405;hb=b84ce655d31a2236734c788fd3292c10d5d9f0b1;hp=9e261ba7513d4b44432f958bcf52794f4ae26f34;hpb=5cfb672ddef7c4e6a7bd424345c8f962a6f94dfc;p=mech_eap.git diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 9e261ba..ce631dd 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / Configuration parser and common functions - * Copyright (c) 2003-2012, Jouni Malinen + * Copyright (c) 2003-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -15,6 +15,7 @@ #include "rsn_supp/wpa.h" #include "eap_peer/eap.h" #include "p2p/p2p.h" +#include "fst/fst.h" #include "config.h" @@ -31,7 +32,11 @@ struct parse_data { /* 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); @@ -58,7 +63,7 @@ static int wpa_config_parse_str(const struct parse_data *data, 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) { @@ -104,6 +109,21 @@ static int wpa_config_parse_str(const struct parse_data *data, 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) @@ -189,6 +209,9 @@ static int wpa_config_parse_int(const struct parse_data *data, line, value); return -1; } + + if (*dst == val) + return 1; *dst = val; wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst); @@ -225,7 +248,7 @@ static char * wpa_config_write_int(const struct parse_data *data, if (value == NULL) return NULL; res = os_snprintf(value, 20, "%d", *src); - if (res < 0 || res >= 20) { + if (os_snprintf_error(20, res)) { os_free(value); return NULL; } @@ -235,6 +258,99 @@ static char * wpa_config_write_int(const struct parse_data *data, #endif /* NO_CONFIG_WRITE */ +static int wpa_config_parse_addr_list(const struct parse_data *data, + int line, const char *value, + u8 **list, size_t *num, char *name, + u8 abort_on_error, u8 masked) +{ + const char *pos; + u8 *buf, *n, addr[2 * ETH_ALEN]; + size_t count; + + buf = NULL; + count = 0; + + pos = value; + while (pos && *pos) { + while (*pos == ' ') + pos++; + + if (hwaddr_masked_aton(pos, addr, &addr[ETH_ALEN], masked)) { + if (abort_on_error || count == 0) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid %s address '%s'", + line, name, value); + os_free(buf); + return -1; + } + /* continue anyway since this could have been from a + * truncated configuration file line */ + wpa_printf(MSG_INFO, + "Line %d: Ignore likely truncated %s address '%s'", + line, name, pos); + } else { + n = os_realloc_array(buf, count + 1, 2 * ETH_ALEN); + if (n == NULL) { + os_free(buf); + return -1; + } + buf = n; + os_memmove(buf + 2 * ETH_ALEN, buf, + count * 2 * ETH_ALEN); + os_memcpy(buf, addr, 2 * ETH_ALEN); + count++; + wpa_printf(MSG_MSGDUMP, + "%s: addr=" MACSTR " mask=" MACSTR, + name, MAC2STR(addr), + MAC2STR(&addr[ETH_ALEN])); + } + + pos = os_strchr(pos, ' '); + } + + os_free(*list); + *list = buf; + *num = count; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_addr_list(const struct parse_data *data, + const u8 *list, size_t num, char *name) +{ + char *value, *end, *pos; + int res; + size_t i; + + if (list == NULL || num == 0) + return NULL; + + value = os_malloc(2 * 20 * num); + if (value == NULL) + return NULL; + pos = value; + end = value + 2 * 20 * num; + + for (i = num; i > 0; i--) { + const u8 *a = list + (i - 1) * 2 * ETH_ALEN; + const u8 *m = a + ETH_ALEN; + + if (i < num) + *pos++ = ' '; + res = hwaddr_mask_txt(pos, end - pos, a, m); + if (res < 0) { + os_free(value); + return NULL; + } + pos += res; + } + + return value; +} +#endif /* NO_CONFIG_WRITE */ + static int wpa_config_parse_bssid(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) @@ -270,7 +386,7 @@ static char * wpa_config_write_bssid(const struct parse_data *data, if (value == NULL) return NULL; res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid)); - if (res < 0 || res >= 20) { + if (os_snprintf_error(20, res)) { os_free(value); return NULL; } @@ -280,6 +396,50 @@ static char * wpa_config_write_bssid(const struct parse_data *data, #endif /* NO_CONFIG_WRITE */ +static int wpa_config_parse_bssid_blacklist(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_addr_list(data, line, value, + &ssid->bssid_blacklist, + &ssid->num_bssid_blacklist, + "bssid_blacklist", 1, 1); +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid_blacklist(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_addr_list(data, ssid->bssid_blacklist, + ssid->num_bssid_blacklist, + "bssid_blacklist"); +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_bssid_whitelist(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_addr_list(data, line, value, + &ssid->bssid_whitelist, + &ssid->num_bssid_whitelist, + "bssid_whitelist", 1, 1); +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid_whitelist(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_addr_list(data, ssid->bssid_whitelist, + ssid->num_bssid_whitelist, + "bssid_whitelist"); +} +#endif /* NO_CONFIG_WRITE */ + + static int wpa_config_parse_psk(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) @@ -318,9 +478,17 @@ static int wpa_config_parse_psk(const struct parse_data *data, } wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)", (u8 *) value, len); + if (has_ctrl_char((u8 *) value, len)) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid passphrase character", + line); + return -1; + } 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); @@ -358,9 +526,15 @@ static char * wpa_config_write_psk(const struct parse_data *data, if (ssid->ext_psk) { size_t len = 4 + os_strlen(ssid->ext_psk) + 1; char *buf = os_malloc(len); + int res; + if (buf == NULL) return NULL; - os_snprintf(buf, len, "ext:%s", ssid->ext_psk); + res = os_snprintf(buf, len, "ext:%s", ssid->ext_psk); + if (os_snprintf_error(len, res)) { + os_free(buf); + buf = NULL; + } return buf; } #endif /* CONFIG_EXT_PASSWORD */ @@ -425,6 +599,8 @@ static int wpa_config_parse_proto(const struct parse_data *data, errors++; } + if (!errors && ssid->proto == val) + return 1; wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val); ssid->proto = val; return errors ? -1 : 0; @@ -446,7 +622,7 @@ static char * wpa_config_write_proto(const struct parse_data *data, if (ssid->proto & WPA_PROTO_WPA) { ret = os_snprintf(pos, end - pos, "%sWPA", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return buf; pos += ret; } @@ -454,7 +630,7 @@ static char * wpa_config_write_proto(const struct parse_data *data, if (ssid->proto & WPA_PROTO_RSN) { ret = os_snprintf(pos, end - pos, "%sRSN", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return buf; pos += ret; } @@ -462,7 +638,7 @@ static char * wpa_config_write_proto(const struct parse_data *data, if (ssid->proto & WPA_PROTO_OSEN) { ret = os_snprintf(pos, end - pos, "%sOSEN", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return buf; pos += ret; } @@ -535,8 +711,14 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, else if (os_strcmp(start, "OSEN") == 0) val |= WPA_KEY_MGMT_OSEN; #endif /* CONFIG_HS20 */ +#ifdef CONFIG_SUITEB else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; +#endif /* CONFIG_SUITEB */ +#ifdef CONFIG_SUITEB192 + else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; +#endif /* CONFIG_SUITEB192 */ else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); @@ -555,6 +737,8 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, 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; @@ -576,7 +760,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { ret = os_snprintf(pos, end - pos, "%sWPA-PSK", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -586,7 +770,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { ret = os_snprintf(pos, end - pos, "%sWPA-EAP", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -596,7 +780,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { ret = os_snprintf(pos, end - pos, "%sIEEE8021X", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -606,7 +790,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) { ret = os_snprintf(pos, end - pos, "%sNONE", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -616,7 +800,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) { ret = os_snprintf(pos, end - pos, "%sWPA-NONE", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -627,7 +811,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) { ret = os_snprintf(pos, end - pos, "%sFT-PSK", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -637,7 +821,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { ret = os_snprintf(pos, end - pos, "%sFT-EAP", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -649,7 +833,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { ret = os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -659,7 +843,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -671,7 +855,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { ret = os_snprintf(pos, end - pos, "%sWPS", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -683,7 +867,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { ret = os_snprintf(pos, end - pos, "%sSAE", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -693,7 +877,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_FT_SAE) { ret = os_snprintf(pos, end - pos, "%sFT-SAE", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -705,7 +889,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, if (ssid->key_mgmt & WPA_KEY_MGMT_OSEN) { ret = os_snprintf(pos, end - pos, "%sOSEN", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -713,15 +897,29 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, } #endif /* CONFIG_HS20 */ +#ifdef CONFIG_SUITEB if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } pos += ret; } +#endif /* CONFIG_SUITEB */ + +#ifdef CONFIG_SUITEB192 + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { + ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B-192", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_SUITEB192 */ if (pos == buf) { os_free(buf); @@ -735,6 +933,9 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, static int wpa_config_parse_cipher(int line, const char *value) { +#ifdef CONFIG_NO_WPA + return -1; +#else /* CONFIG_NO_WPA */ int val = wpa_parse_cipher(value); if (val < 0) { wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", @@ -747,12 +948,16 @@ static int wpa_config_parse_cipher(int line, const char *value) return -1; } return val; +#endif /* CONFIG_NO_WPA */ } #ifndef NO_CONFIG_WRITE static char * wpa_config_write_cipher(int cipher) { +#ifdef CONFIG_NO_WPA + return NULL; +#else /* CONFIG_NO_WPA */ char *buf = os_zalloc(50); if (buf == NULL) return NULL; @@ -763,6 +968,7 @@ static char * wpa_config_write_cipher(int cipher) } return buf; +#endif /* CONFIG_NO_WPA */ } #endif /* NO_CONFIG_WRITE */ @@ -781,6 +987,8 @@ static int wpa_config_parse_pairwise(const struct parse_data *data, return -1; } + if (ssid->pairwise_cipher == val) + return 1; wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val); ssid->pairwise_cipher = val; return 0; @@ -804,12 +1012,21 @@ static int wpa_config_parse_group(const struct parse_data *data, val = wpa_config_parse_cipher(line, value); if (val == -1) return -1; + + /* + * Backwards compatibility - filter out WEP ciphers that were previously + * allowed. + */ + val &= ~(WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40); + if (val & ~WPA_ALLOWED_GROUP_CIPHERS) { wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher " "(0x%x).", line, val); return -1; } + if (ssid->group_cipher == val) + return 1; wpa_printf(MSG_MSGDUMP, "group: 0x%x", val); ssid->group_cipher = val; return 0; @@ -871,6 +1088,8 @@ static int wpa_config_parse_auth_alg(const struct parse_data *data, 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; @@ -892,7 +1111,7 @@ static char * wpa_config_write_auth_alg(const struct parse_data *data, if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) { ret = os_snprintf(pos, end - pos, "%sOPEN", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -902,7 +1121,7 @@ static char * wpa_config_write_auth_alg(const struct parse_data *data, if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) { ret = os_snprintf(pos, end - pos, "%sSHARED", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -912,7 +1131,7 @@ static char * wpa_config_write_auth_alg(const struct parse_data *data, if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) { ret = os_snprintf(pos, end - pos, "%sLEAP", pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -1033,7 +1252,7 @@ static char * wpa_config_write_freqs(const struct parse_data *data, for (i = 0; freqs[i]; i++) { ret = os_snprintf(pos, end - pos, "%s%u", i == 0 ? "" : " ", freqs[i]); - if (ret < 0 || ret >= end - pos) { + if (os_snprintf_error(end - pos, ret)) { end[-1] = '\0'; return buf; } @@ -1125,6 +1344,32 @@ static int wpa_config_parse_eap(const struct parse_data *data, 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); @@ -1133,6 +1378,7 @@ static int wpa_config_parse_eap(const struct parse_data *data, } +#ifndef NO_CONFIG_WRITE static char * wpa_config_write_eap(const struct parse_data *data, struct wpa_ssid *ssid) { @@ -1156,7 +1402,7 @@ static char * wpa_config_write_eap(const struct parse_data *data, if (name) { ret = os_snprintf(pos, end - pos, "%s%s", pos == buf ? "" : " ", name); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) break; pos += ret; } @@ -1166,6 +1412,7 @@ static char * wpa_config_write_eap(const struct parse_data *data, return buf; } +#endif /* NO_CONFIG_WRITE */ static int wpa_config_parse_password(const struct parse_data *data, @@ -1175,6 +1422,8 @@ static int wpa_config_parse_password(const struct parse_data *data, 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; @@ -1238,6 +1487,12 @@ static int wpa_config_parse_password(const struct parse_data *data, 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; @@ -1248,6 +1503,7 @@ static int wpa_config_parse_password(const struct parse_data *data, } +#ifndef NO_CONFIG_WRITE static char * wpa_config_write_password(const struct parse_data *data, struct wpa_ssid *ssid) { @@ -1281,6 +1537,7 @@ static char * wpa_config_write_password(const struct parse_data *data, return buf; } +#endif /* NO_CONFIG_WRITE */ #endif /* IEEE8021X_EAPOL */ @@ -1310,7 +1567,7 @@ static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, os_memcpy(key, buf, *len); str_clear_free(buf); res = os_snprintf(title, sizeof(title), "wep_key%d", idx); - if (res >= 0 && (size_t) res < sizeof(title)) + if (!os_snprintf_error(sizeof(title), res)) wpa_hexdump_key(MSG_MSGDUMP, title, key, *len); return 0; } @@ -1433,7 +1690,7 @@ static char * wpa_config_write_go_p2p_dev_addr(const struct parse_data *data, if (value == NULL) return NULL; res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->go_p2p_dev_addr)); - if (res < 0 || res >= 20) { + if (os_snprintf_error(20, res)) { os_free(value); return NULL; } @@ -1447,53 +1704,10 @@ static int wpa_config_parse_p2p_client_list(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) { - const char *pos; - u8 *buf, *n, addr[ETH_ALEN]; - size_t count; - - buf = NULL; - count = 0; - - pos = value; - while (pos && *pos) { - while (*pos == ' ') - pos++; - - if (hwaddr_aton(pos, addr)) { - if (count == 0) { - wpa_printf(MSG_ERROR, "Line %d: Invalid " - "p2p_client_list address '%s'.", - line, value); - os_free(buf); - return -1; - } - /* continue anyway since this could have been from a - * truncated configuration file line */ - wpa_printf(MSG_INFO, "Line %d: Ignore likely " - "truncated p2p_client_list address '%s'", - line, pos); - } else { - n = os_realloc_array(buf, count + 1, ETH_ALEN); - if (n == NULL) { - os_free(buf); - return -1; - } - buf = n; - os_memmove(buf + ETH_ALEN, buf, count * ETH_ALEN); - os_memcpy(buf, addr, ETH_ALEN); - count++; - wpa_hexdump(MSG_MSGDUMP, "p2p_client_list", - addr, ETH_ALEN); - } - - pos = os_strchr(pos, ' '); - } - - os_free(ssid->p2p_client_list); - ssid->p2p_client_list = buf; - ssid->num_p2p_clients = count; - - return 0; + return wpa_config_parse_addr_list(data, line, value, + &ssid->p2p_client_list, + &ssid->num_p2p_clients, + "p2p_client_list", 0, 0); } @@ -1501,34 +1715,9 @@ static int wpa_config_parse_p2p_client_list(const struct parse_data *data, static char * wpa_config_write_p2p_client_list(const struct parse_data *data, struct wpa_ssid *ssid) { - char *value, *end, *pos; - int res; - size_t i; - - if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0) - return NULL; - - value = os_malloc(20 * ssid->num_p2p_clients); - if (value == NULL) - return NULL; - pos = value; - end = value + 20 * ssid->num_p2p_clients; - - for (i = ssid->num_p2p_clients; i > 0; i--) { - res = os_snprintf(pos, end - pos, MACSTR " ", - MAC2STR(ssid->p2p_client_list + - (i - 1) * ETH_ALEN)); - if (res < 0 || res >= end - pos) { - os_free(value); - return NULL; - } - pos += res; - } - - if (pos > value) - pos[-1] = '\0'; - - return value; + return wpa_config_write_addr_list(data, ssid->p2p_client_list, + ssid->num_p2p_clients, + "p2p_client_list"); } #endif /* NO_CONFIG_WRITE */ @@ -1591,56 +1780,35 @@ static char * wpa_config_write_psk_list(const struct parse_data *data, #ifdef CONFIG_MESH -static int wpa_config_parse_mesh_ht_mode(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) +static int wpa_config_parse_mesh_basic_rates(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) { - int htval = 0; - - if (os_strcmp(value, "NOHT") == 0) - htval = CHAN_NO_HT; - else if (os_strcmp(value, "HT20") == 0) - htval = CHAN_HT20; - else if (os_strcmp(value, "HT40-") == 0) - htval = CHAN_HT40MINUS; - else if (os_strcmp(value, "HT40+") == 0) - htval = CHAN_HT40PLUS; - else { - wpa_printf(MSG_ERROR, - "Line %d: no ht_mode configured.", line); + int *rates = wpa_config_parse_int_array(value); + + if (rates == NULL) { + wpa_printf(MSG_ERROR, "Line %d: Invalid mesh_basic_rates '%s'", + line, value); return -1; } + if (rates[0] == 0) { + os_free(rates); + rates = NULL; + } + + os_free(ssid->mesh_basic_rates); + ssid->mesh_basic_rates = rates; - wpa_printf(MSG_MSGDUMP, "mesh_ht_mode: 0x%x", htval); - ssid->mesh_ht_mode = htval; return 0; } #ifndef NO_CONFIG_WRITE -static char * wpa_config_write_mesh_ht_mode(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - char *val; - switch (ssid->mesh_ht_mode) { - default: - val = NULL; - break; - case CHAN_NO_HT: - val = "NOHT"; - break; - case CHAN_HT20: - val = "HT20"; - break; - case CHAN_HT40MINUS: - val = "HT40-"; - break; - case CHAN_HT40PLUS: - val = "HT40+"; - break; - } - return val ? os_strdup(val) : NULL; +static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_freqs(data, ssid->mesh_basic_rates); } #endif /* NO_CONFIG_WRITE */ @@ -1736,10 +1904,13 @@ static char * wpa_config_write_mesh_ht_mode(const struct parse_data *data, * functions. */ static const struct parse_data ssid_fields[] = { - { STR_RANGE(ssid, 0, MAX_SSID_LEN) }, + { STR_RANGE(ssid, 0, SSID_MAX_LEN) }, { INT_RANGE(scan_ssid, 0, 1) }, { FUNC(bssid) }, + { FUNC(bssid_blacklist) }, + { FUNC(bssid_whitelist) }, { FUNC_KEY(psk) }, + { INT(mem_only_psk) }, { FUNC(proto) }, { FUNC(key_mgmt) }, { INT(bg_scan_period) }, @@ -1748,6 +1919,8 @@ static const struct parse_data ssid_fields[] = { { FUNC(auth_alg) }, { FUNC(scan_freq) }, { FUNC(freq_list) }, + { INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT, + VHT_CHANWIDTH_80P80MHZ) }, #ifdef IEEE8021X_EAPOL { FUNC(eap) }, { STR_LENe(identity) }, @@ -1762,6 +1935,7 @@ static const struct parse_data ssid_fields[] = { { STRe(subject_match) }, { STRe(altsubject_match) }, { STRe(domain_suffix_match) }, + { STRe(domain_match) }, { STRe(ca_cert2) }, { STRe(ca_path2) }, { STRe(client_cert2) }, @@ -1771,6 +1945,7 @@ static const struct parse_data ssid_fields[] = { { STRe(subject_match2) }, { STRe(altsubject_match2) }, { STRe(domain_suffix_match2) }, + { STRe(domain_match2) }, { STRe(phase1) }, { STRe(phase2) }, { STRe(pcsc) }, @@ -1789,6 +1964,7 @@ static const struct parse_data ssid_fields[] = { { INT(eapol_flags) }, { INTe(sim_num) }, { STRe(openssl_ciphers) }, + { INTe(erp) }, #endif /* IEEE8021X_EAPOL */ { FUNC_KEY(wep_key0) }, { FUNC_KEY(wep_key1) }, @@ -1817,8 +1993,16 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(peerkey, 0, 1) }, { INT_RANGE(mixed_cell, 0, 1) }, { INT_RANGE(frequency, 0, 65000) }, + { INT_RANGE(fixed_freq, 0, 1) }, +#ifdef CONFIG_ACS + { INT_RANGE(acs, 0, 1) }, +#endif /* CONFIG_ACS */ #ifdef CONFIG_MESH - { FUNC(mesh_ht_mode) }, + { FUNC(mesh_basic_rates) }, + { INT(dot11MeshMaxRetries) }, + { INT(dot11MeshRetryTimeout) }, + { INT(dot11MeshConfirmTimeout) }, + { INT(dot11MeshHoldingTimeout) }, #endif /* CONFIG_MESH */ { INT(wpa_ptk_rekey) }, { STR(bgscan) }, @@ -1870,6 +2054,8 @@ static const struct parse_data ssid_fields[] = { { INT(update_identifier) }, #endif /* CONFIG_HS20 */ { INT_RANGE(mac_addr, 0, 2) }, + { INT_RANGE(pbss, 0, 2) }, + { INT_RANGE(wps_disabled, 0, 1) }, }; #undef OFFSET @@ -1991,6 +2177,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap) os_free(eap->subject_match); os_free(eap->altsubject_match); os_free(eap->domain_suffix_match); + os_free(eap->domain_match); os_free(eap->ca_cert2); os_free(eap->ca_path2); os_free(eap->client_cert2); @@ -2000,6 +2187,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap) os_free(eap->subject_match2); os_free(eap->altsubject_match2); os_free(eap->domain_suffix_match2); + os_free(eap->domain_match2); os_free(eap->phase1); os_free(eap->phase2); os_free(eap->pcsc); @@ -2035,7 +2223,6 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) struct psk_list_entry *psk; os_free(ssid->ssid); - os_memset(ssid->psk, 0, sizeof(ssid->psk)); str_clear_free(ssid->passphrase); os_free(ssid->ext_psk); #ifdef IEEE8021X_EAPOL @@ -2046,15 +2233,20 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) os_free(ssid->freq_list); os_free(ssid->bgscan); os_free(ssid->p2p_client_list); + os_free(ssid->bssid_blacklist); + os_free(ssid->bssid_whitelist); #ifdef CONFIG_HT_OVERRIDES os_free(ssid->ht_mcs); #endif /* CONFIG_HT_OVERRIDES */ +#ifdef CONFIG_MESH + os_free(ssid->mesh_basic_rates); +#endif /* CONFIG_MESH */ while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry, list))) { dl_list_del(&psk->list); - os_free(psk); + bin_clear_free(psk, sizeof(*psk)); } - os_free(ssid); + bin_clear_free(ssid, sizeof(*ssid)); } @@ -2116,6 +2308,7 @@ void wpa_config_free(struct wpa_config *config) { struct wpa_ssid *ssid, *prev = NULL; struct wpa_cred *cred, *cprev; + int i; ssid = config->ssid; while (ssid) { @@ -2134,6 +2327,8 @@ void wpa_config_free(struct wpa_config *config) wpa_config_flush_blobs(config); wpabuf_free(config->wps_vendor_ext_m1); + for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) + wpabuf_free(config->wps_vendor_ext[i]); os_free(config->ctrl_interface); os_free(config->ctrl_interface_group); os_free(config->opensc_engine_path); @@ -2162,7 +2357,14 @@ void wpa_config_free(struct wpa_config *config) os_free(config->sae_groups); wpabuf_free(config->ap_vendor_elements); os_free(config->osu_dir); + os_free(config->bgscan); os_free(config->wowlan_triggers); + os_free(config->fst_group_id); + os_free(config->sched_scan_plans); +#ifdef CONFIG_MBO + os_free(config->non_pref_chan); +#endif /* CONFIG_MBO */ + os_free(config); } @@ -2299,7 +2501,10 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM; #endif /* IEEE8021X_EAPOL */ #ifdef CONFIG_MESH - ssid->mesh_ht_mode = DEFAULT_MESH_HT_MODE; + ssid->dot11MeshMaxRetries = DEFAULT_MESH_MAX_RETRIES; + ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT; + ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT; + ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT; #endif /* CONFIG_MESH */ #ifdef CONFIG_HT_OVERRIDES ssid->disable_ht = DEFAULT_DISABLE_HT; @@ -2342,7 +2547,8 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) * @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 @@ -2363,7 +2569,8 @@ int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *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); @@ -2419,6 +2626,9 @@ int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var, */ char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys) { +#ifdef NO_CONFIG_WRITE + return NULL; +#else /* NO_CONFIG_WRITE */ const struct parse_data *field; char *key, *value; size_t i; @@ -2459,11 +2669,11 @@ char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys) return props; err: - value = *props; - while (value) - os_free(value++); + for (i = 0; props[i]; i++) + os_free(props[i]); os_free(props); return NULL; +#endif /* NO_CONFIG_WRITE */ } @@ -2489,8 +2699,19 @@ char * wpa_config_get(struct wpa_ssid *ssid, const char *var) for (i = 0; i < NUM_SSID_FIELDS; i++) { const struct parse_data *field = &ssid_fields[i]; - if (os_strcmp(var, field->name) == 0) - return field->writer(field, ssid); + if (os_strcmp(var, field->name) == 0) { + char *ret = field->writer(field, ssid); + + if (ret && has_newline(ret)) { + wpa_printf(MSG_ERROR, + "Found newline in value for %s; not returning it", + var); + os_free(ret); + ret = NULL; + } + + return ret; + } } return NULL; @@ -2675,6 +2896,8 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, if (os_strcmp(var, "password") == 0 && os_strncmp(value, "ext:", 4) == 0) { + if (has_newline(value)) + return -1; str_clear_free(cred->password); cred->password = os_strdup(value); cred->ext_password = 1; @@ -2725,9 +2948,14 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, } val = wpa_config_parse_string(value, &len); - if (val == NULL) { + if (val == NULL || + (os_strcmp(var, "excluded_ssid") != 0 && + os_strcmp(var, "roaming_consortium") != 0 && + os_strcmp(var, "required_roaming_consortium") != 0 && + has_newline(val))) { wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string " "value '%s'.", line, var, value); + os_free(val); return -1; } @@ -2850,7 +3078,7 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, if (os_strcmp(var, "excluded_ssid") == 0) { struct excluded_ssid *e; - if (len > MAX_SSID_LEN) { + if (len > SSID_MAX_LEN) { wpa_printf(MSG_ERROR, "Line %d: invalid " "excluded_ssid length %d", line, (int) len); os_free(val); @@ -2951,12 +3179,18 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, static char * alloc_int_str(int val) { + const unsigned int bufsize = 20; char *buf; + int res; - buf = os_malloc(20); + buf = os_malloc(bufsize); if (buf == NULL) return NULL; - os_snprintf(buf, 20, "%d", val); + res = os_snprintf(buf, bufsize, "%d", val); + if (os_snprintf_error(bufsize, res)) { + os_free(buf); + buf = NULL; + } return buf; } @@ -3027,7 +3261,7 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) ret = os_snprintf(pos, end - pos, "%s%u", i > 0 ? "\n" : "", cred->req_conn_capab_proto[i]); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return buf; pos += ret; @@ -3039,7 +3273,7 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) "%s%d", j > 0 ? "," : ":", ports[j]); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return buf; pos += ret; } @@ -3108,7 +3342,7 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) for (i = 0; i < cred->num_domain; i++) { ret = os_snprintf(pos, end - pos, "%s%s", i > 0 ? "\n" : "", cred->domain[i]); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return buf; pos += ret; } @@ -3173,7 +3407,7 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) ret = os_snprintf(pos, end - pos, "%s%s", i > 0 ? "\n" : "", wpa_ssid_txt(e->ssid, e->ssid_len)); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return buf; pos += ret; } @@ -3203,7 +3437,7 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) i > 0 ? "\n" : "", p->fqdn, p->exact_match, p->priority, p->country); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return buf; pos += ret; } @@ -3394,11 +3628,17 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->eapol_version = DEFAULT_EAPOL_VERSION; config->ap_scan = DEFAULT_AP_SCAN; config->user_mpm = DEFAULT_USER_MPM; + config->max_peer_links = DEFAULT_MAX_PEER_LINKS; + config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY; + config->dot11RSNASAERetransPeriod = + DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD; config->fast_reauth = DEFAULT_FAST_REAUTH; config->p2p_go_intent = DEFAULT_P2P_GO_INTENT; config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS; + config->p2p_go_freq_change_policy = DEFAULT_P2P_GO_FREQ_MOVE; config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY; config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN; + config->p2p_go_ctwindow = DEFAULT_P2P_GO_CTWINDOW; config->bss_max_count = DEFAULT_BSS_MAX_COUNT; config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE; config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT; @@ -3412,6 +3652,12 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY; config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME; config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD; + config->cert_in_cb = DEFAULT_CERT_IN_CB; + config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION; + +#ifdef CONFIG_MBO + config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA; +#endif /* CONFIG_MBO */ if (ctrl_interface) config->ctrl_interface = os_strdup(ctrl_interface); @@ -3451,6 +3697,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; }; @@ -3516,6 +3764,12 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data, return -1; } + if (has_newline(pos)) { + wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline", + line, data->name); + return -1; + } + tmp = os_strdup(pos); if (tmp == NULL) return -1; @@ -3554,22 +3808,12 @@ static int wpa_global_config_parse_bin(const struct global_parse_data *data, struct wpa_config *config, int line, const char *pos) { - size_t len; struct wpabuf **dst, *tmp; - len = os_strlen(pos); - if (len & 0x01) + tmp = wpabuf_parse_bin(pos); + if (!tmp) return -1; - tmp = wpabuf_alloc(len / 2); - if (tmp == NULL) - return -1; - - if (hexstr2bin(pos, wpabuf_put(tmp, len / 2), len / 2)) { - wpabuf_free(tmp); - return -1; - } - dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1); wpabuf_free(*dst); *dst = tmp; @@ -3910,22 +4154,81 @@ 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 CONFIG_P2P +static int wpa_config_get_ipv4(const char *name, struct wpa_config *config, + long offset, char *buf, size_t buflen, + int pretty_print) +{ + void *val = ((u8 *) config) + (long) offset; + int res; + char addr[INET_ADDRSTRLEN]; + + if (!val || !inet_ntop(AF_INET, val, addr, sizeof(addr))) + return -1; + + if (pretty_print) + res = os_snprintf(buf, buflen, "%s=%s\n", name, addr); + else + res = os_snprintf(buf, buflen, "%s", addr); + + if (os_snprintf_error(buflen, res)) + res = -1; + + return res; +} +#endif /* CONFIG_P2P */ + + #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, wpa_config_get_ipv4, \ + OFFSET(f), NULL, NULL static const struct global_parse_data global_fields[] = { #ifdef CONFIG_CTRL_IFACE @@ -3942,6 +4245,9 @@ static const struct global_parse_data global_fields[] = { { FUNC(bgscan), 0 }, #ifdef CONFIG_MESH { INT(user_mpm), 0 }, + { INT_RANGE(max_peer_links, 0, 255), 0 }, + { INT(mesh_max_inactivity), 0 }, + { INT(dot11RSNASAERetransPeriod), 0 }, #endif /* CONFIG_MESH */ { INT(disable_scan_offload), 0 }, { INT(fast_reauth), 0 }, @@ -3962,7 +4268,8 @@ static const struct global_parse_data global_fields[] = { { FUNC_NO_VAR(load_dynamic_eap), 0 }, #ifdef CONFIG_WPS { FUNC(uuid), CFG_CHANGED_UUID }, - { STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME }, + { STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN), + CFG_CHANGED_DEVICE_NAME }, { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING }, { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING }, { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING }, @@ -3975,8 +4282,8 @@ static const struct global_parse_data global_fields[] = { #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE }, - { INT(p2p_listen_reg_class), 0 }, - { INT(p2p_listen_channel), 0 }, + { INT(p2p_listen_reg_class), CFG_CHANGED_P2P_LISTEN_CHANNEL }, + { INT(p2p_listen_channel), CFG_CHANGED_P2P_LISTEN_CHANNEL }, { INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL }, { INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL }, { INT_RANGE(p2p_go_intent, 0, 15), 0 }, @@ -3984,6 +4291,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(persistent_reconnect, 0, 1), 0 }, { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS }, { INT(p2p_group_idle), 0 }, + { INT_RANGE(p2p_go_freq_change_policy, 0, P2P_GO_FREQ_MOVE_MAX), 0 }, { INT_RANGE(p2p_passphrase_len, 8, 63), CFG_CHANGED_P2P_PASSPHRASE_LEN }, { FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN }, @@ -3993,12 +4301,14 @@ static const struct global_parse_data global_fields[] = { { INT(p2p_go_ht40), 0 }, { INT(p2p_go_vht), 0 }, { INT(p2p_disabled), 0 }, + { INT_RANGE(p2p_go_ctwindow, 0, 127), 0 }, { INT(p2p_no_group_iface), 0 }, { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 }, { IPV4(ip_addr_go), 0 }, { IPV4(ip_addr_mask), 0 }, { IPV4(ip_addr_start), 0 }, { IPV4(ip_addr_end), 0 }, + { INT_RANGE(p2p_cli_probe, 0, 1), 0 }, #endif /* CONFIG_P2P */ { FUNC(country), CFG_CHANGED_COUNTRY }, { INT(bss_max_count), 0 }, @@ -4042,6 +4352,22 @@ static const struct global_parse_data global_fields[] = { { INT(rand_addr_lifetime), 0 }, { INT(preassoc_mac_addr), 0 }, { INT(key_mgmt_offload), 0}, + { INT(passive_scan), 0 }, + { INT(reassoc_same_bss_optim), 0 }, + { INT(wps_priority), 0}, +#ifdef CONFIG_FST + { STR_RANGE(fst_group_id, 1, FST_MAX_GROUP_ID_LEN), 0 }, + { INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 }, + { INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 }, +#endif /* CONFIG_FST */ + { INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 }, + { STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS }, +#ifdef CONFIG_MBO + { STR(non_pref_chan), 0 }, + { INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE, + MBO_CELL_CAPA_NOT_SUPPORTED), 0 }, +#endif /*CONFIG_MBO */ + { INT(gas_address3), 0 }, }; #undef FUNC @@ -4056,6 +4382,67 @@ 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_get_num_global_field_names(void) +{ + return NUM_GLOBAL_FIELDS; +} + + +const char * wpa_config_get_global_field_name(unsigned int i, int *no_var) +{ + if (i >= NUM_GLOBAL_FIELDS) + return NULL; + + if (no_var) + *no_var = !global_fields[i].param1; + return global_fields[i].name; +} + + int wpa_config_process_global(struct wpa_config *config, char *pos, int line) { size_t i;