Add network specific BSSID black and white lists
[mech_eap.git] / wpa_supplicant / config.c
index 9e261ba..8925705 100644 (file)
@@ -225,7 +225,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 +235,94 @@ 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)
+{
+       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 (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, 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, name, 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(20 * num);
+       if (value == NULL)
+               return NULL;
+       pos = value;
+       end = value + 20 * num;
+
+       for (i = num; i > 0; i--) {
+               res = os_snprintf(pos, end - pos, MACSTR " ",
+                                 MAC2STR(list + (i - 1) * ETH_ALEN));
+               if (os_snprintf_error(end - pos, res)) {
+                       os_free(value);
+                       return NULL;
+               }
+               pos += res;
+       }
+
+       if (pos > value)
+               pos[-1] = '\0';
+
+       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 +358,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 +368,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);
+}
+
+
+#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);
+}
+
+
+#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)
@@ -358,9 +490,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 */
@@ -446,7 +584,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 +592,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 +600,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;
        }
@@ -576,7 +714,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 +724,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 +734,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 +744,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 +754,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 +765,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 +775,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 +787,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 +797,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 +809,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 +821,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 +831,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 +843,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;
                }
@@ -716,7 +854,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
        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;
                }
@@ -892,7 +1030,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 +1040,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 +1050,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 +1171,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;
                }
@@ -1156,7 +1294,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;
                }
@@ -1310,7 +1448,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 +1571,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 +1585,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);
 }
 
 
@@ -1501,34 +1596,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 +1661,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 */
@@ -1739,6 +1788,8 @@ static const struct parse_data ssid_fields[] = {
        { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
        { INT_RANGE(scan_ssid, 0, 1) },
        { FUNC(bssid) },
+       { FUNC(bssid_blacklist) },
+       { FUNC(bssid_whitelist) },
        { FUNC_KEY(psk) },
        { FUNC(proto) },
        { FUNC(key_mgmt) },
@@ -1789,6 +1840,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) },
@@ -1818,7 +1870,11 @@ static const struct parse_data ssid_fields[] = {
        { INT_RANGE(mixed_cell, 0, 1) },
        { INT_RANGE(frequency, 0, 65000) },
 #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) },
@@ -2035,7 +2091,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
@@ -2049,12 +2104,15 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
 #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 +2174,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 +2193,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);
@@ -2299,7 +2360,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;
@@ -2951,12 +3015,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 +3097,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 +3109,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 +3178,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 +3243,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 +3273,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,6 +3464,7 @@ 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->fast_reauth = DEFAULT_FAST_REAUTH;
        config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
        config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
@@ -3942,6 +4013,7 @@ 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 },
 #endif /* CONFIG_MESH */
        { INT(disable_scan_offload), 0 },
        { INT(fast_reauth), 0 },