]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - hostapd/config_file.c
AP: Support Extended Key ID
[thirdparty/hostap.git] / hostapd / config_file.c
index 0452b78725c4996e5afcee094e4287980386504e..2bc0679b5c3d4482a1284cc5d4949a737d903dd2 100644 (file)
 #include "config_file.h"
 
 
-#ifndef CONFIG_NO_RADIUS
-#ifdef EAP_SERVER
-static struct hostapd_radius_attr *
-hostapd_parse_radius_attr(const char *value);
-#endif /* EAP_SERVER */
-#endif /* CONFIG_NO_RADIUS */
-
-
 #ifndef CONFIG_NO_VLAN
 static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
                                         const char *fname)
 {
        FILE *f;
-       char buf[128], *pos, *pos2;
+       char buf[128], *pos, *pos2, *pos3;
        int line = 0, vlan_id;
        struct hostapd_vlan *vlan;
 
@@ -82,7 +74,10 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
                pos2 = pos;
                while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
                        pos2++;
-               *pos2 = '\0';
+
+               if (*pos2 != '\0')
+                       *(pos2++) = '\0';
+
                if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
                        wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d "
                                   "in '%s'", line, fname);
@@ -90,6 +85,13 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
                        return -1;
                }
 
+               while (*pos2 == ' ' || *pos2 == '\t')
+                       pos2++;
+               pos3 = pos2;
+               while (*pos3 != ' ' && *pos3 != '\t' && *pos3 != '\0')
+                       pos3++;
+               *pos3 = '\0';
+
                vlan = os_zalloc(sizeof(*vlan));
                if (vlan == NULL) {
                        wpa_printf(MSG_ERROR, "Out of memory while reading "
@@ -102,6 +104,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
                vlan->vlan_desc.untagged = vlan_id;
                vlan->vlan_desc.notempty = !!vlan_id;
                os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
+               os_strlcpy(vlan->bridge, pos2, sizeof(vlan->bridge));
                vlan->next = bss->vlan;
                bss->vlan = vlan;
        }
@@ -649,75 +652,6 @@ hostapd_config_read_radius_addr(struct hostapd_radius_server **server,
 }
 
 
-static struct hostapd_radius_attr *
-hostapd_parse_radius_attr(const char *value)
-{
-       const char *pos;
-       char syntax;
-       struct hostapd_radius_attr *attr;
-       size_t len;
-
-       attr = os_zalloc(sizeof(*attr));
-       if (attr == NULL)
-               return NULL;
-
-       attr->type = atoi(value);
-
-       pos = os_strchr(value, ':');
-       if (pos == NULL) {
-               attr->val = wpabuf_alloc(1);
-               if (attr->val == NULL) {
-                       os_free(attr);
-                       return NULL;
-               }
-               wpabuf_put_u8(attr->val, 0);
-               return attr;
-       }
-
-       pos++;
-       if (pos[0] == '\0' || pos[1] != ':') {
-               os_free(attr);
-               return NULL;
-       }
-       syntax = *pos++;
-       pos++;
-
-       switch (syntax) {
-       case 's':
-               attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
-               break;
-       case 'x':
-               len = os_strlen(pos);
-               if (len & 1)
-                       break;
-               len /= 2;
-               attr->val = wpabuf_alloc(len);
-               if (attr->val == NULL)
-                       break;
-               if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
-                       wpabuf_free(attr->val);
-                       os_free(attr);
-                       return NULL;
-               }
-               break;
-       case 'd':
-               attr->val = wpabuf_alloc(4);
-               if (attr->val)
-                       wpabuf_put_be32(attr->val, atoi(pos));
-               break;
-       default:
-               os_free(attr);
-               return NULL;
-       }
-
-       if (attr->val == NULL) {
-               os_free(attr);
-               return NULL;
-       }
-
-       return attr;
-}
-
 
 static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val)
 {
@@ -777,12 +711,10 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
                        val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
 #endif /* CONFIG_SHA384 */
 #endif /* CONFIG_IEEE80211R_AP */
-#ifdef CONFIG_IEEE80211W
                else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
                        val |= WPA_KEY_MGMT_PSK_SHA256;
                else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
                        val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
-#endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_SAE
                else if (os_strcmp(start, "SAE") == 0)
                        val |= WPA_KEY_MGMT_SAE;
@@ -861,6 +793,7 @@ static int hostapd_config_parse_cipher(int line, const char *value)
 }
 
 
+#ifdef CONFIG_WEP
 static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
                                   char *val)
 {
@@ -911,6 +844,7 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
 
        return 0;
 }
+#endif /* CONFIG_WEP */
 
 
 static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
@@ -1219,7 +1153,6 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value)
 #endif /* CONFIG_IEEE80211R_AP */
 
 
-#ifdef CONFIG_IEEE80211N
 static int hostapd_config_ht_capab(struct hostapd_config *conf,
                                   const char *capab)
 {
@@ -1239,14 +1172,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
        }
        if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]"))
                conf->secondary_channel = 0;
-       if (os_strstr(capab, "[SMPS-STATIC]")) {
-               conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
-               conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC;
-       }
-       if (os_strstr(capab, "[SMPS-DYNAMIC]")) {
-               conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
-               conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC;
-       }
        if (os_strstr(capab, "[GF]"))
                conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
        if (os_strstr(capab, "[SHORT-GI-20]"))
@@ -1280,7 +1205,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
 
        return 0;
 }
-#endif /* CONFIG_IEEE80211N */
 
 
 #ifdef CONFIG_IEEE80211AC
@@ -1368,6 +1292,30 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
 #endif /* CONFIG_IEEE80211AC */
 
 
+#ifdef CONFIG_IEEE80211AX
+
+static u8 find_bit_offset(u8 val)
+{
+       u8 res = 0;
+
+       for (; val; val >>= 1) {
+               if (val & 1)
+                       break;
+               res++;
+       }
+
+       return res;
+}
+
+
+static u8 set_he_cap(int val, u8 mask)
+{
+       return (u8) (mask & (val << find_bit_offset(mask)));
+}
+
+#endif /* CONFIG_IEEE80211AX */
+
+
 #ifdef CONFIG_INTERWORKING
 static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
                                    int line)
@@ -2254,10 +2202,16 @@ static unsigned int parse_tls_flags(const char *val)
                flags |= TLS_CONN_DISABLE_TIME_CHECKS;
        if (os_strstr(val, "[DISABLE-TLSv1.0]"))
                flags |= TLS_CONN_DISABLE_TLSv1_0;
+       if (os_strstr(val, "[ENABLE-TLSv1.0]"))
+               flags |= TLS_CONN_ENABLE_TLSv1_0;
        if (os_strstr(val, "[DISABLE-TLSv1.1]"))
                flags |= TLS_CONN_DISABLE_TLSv1_1;
+       if (os_strstr(val, "[ENABLE-TLSv1.1]"))
+               flags |= TLS_CONN_ENABLE_TLSv1_1;
        if (os_strstr(val, "[DISABLE-TLSv1.2]"))
                flags |= TLS_CONN_DISABLE_TLSv1_2;
+       if (os_strstr(val, "[ENABLE-TLSv1.2]"))
+               flags |= TLS_CONN_ENABLE_TLSv1_2;
        if (os_strstr(val, "[DISABLE-TLSv1.3]"))
                flags |= TLS_CONN_DISABLE_TLSv1_3;
        if (os_strstr(val, "[ENABLE-TLSv1.3]"))
@@ -2272,6 +2226,42 @@ static unsigned int parse_tls_flags(const char *val)
 #endif /* EAP_SERVER */
 
 
+#ifdef CONFIG_AIRTIME_POLICY
+static int add_airtime_weight(struct hostapd_bss_config *bss, char *value)
+{
+       struct airtime_sta_weight *wt;
+       char *pos, *next;
+
+       wt = os_zalloc(sizeof(*wt));
+       if (!wt)
+               return -1;
+
+       /* 02:01:02:03:04:05 10 */
+       pos = value;
+       next = os_strchr(pos, ' ');
+       if (next)
+               *next++ = '\0';
+       if (!next || hwaddr_aton(pos, wt->addr)) {
+               wpa_printf(MSG_ERROR, "Invalid station address: '%s'", pos);
+               os_free(wt);
+               return -1;
+       }
+
+       pos = next;
+       wt->weight = atoi(pos);
+       if (!wt->weight) {
+               wpa_printf(MSG_ERROR, "Invalid weight: '%s'", pos);
+               os_free(wt);
+               return -1;
+       }
+
+       wt->next = bss->airtime_weight_list;
+       bss->airtime_weight_list = wt;
+       return 0;
+}
+#endif /* CONFIG_AIRTIME_POLICY */
+
+
 #ifdef CONFIG_SAE
 static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
 {
@@ -2292,6 +2282,14 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
                pos = pos2 + ETH_ALEN * 3 - 1;
        }
 
+       pos2 = os_strstr(pos, "|vlanid=");
+       if (pos2) {
+               if (!end)
+                       end = pos2;
+               pos2 += 8;
+               pw->vlan_id = atoi(pos2);
+       }
+
        pos2 = os_strstr(pos, "|id=");
        if (pos2) {
                if (!end)
@@ -2327,6 +2325,36 @@ fail:
 #endif /* CONFIG_SAE */
 
 
+#ifdef CONFIG_DPP2
+static int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss,
+                                       const char *pos)
+{
+       struct dpp_controller_conf *conf;
+       char *val;
+
+       conf = os_zalloc(sizeof(*conf));
+       if (!conf)
+               return -1;
+       val = get_param(pos, "ipaddr=");
+       if (!val || hostapd_parse_ip_addr(val, &conf->ipaddr))
+               goto fail;
+       os_free(val);
+       val = get_param(pos, "pkhash=");
+       if (!val || os_strlen(val) != 2 * SHA256_MAC_LEN ||
+           hexstr2bin(val, conf->pkhash, SHA256_MAC_LEN) < 0)
+               goto fail;
+       os_free(val);
+       conf->next = bss->dpp_controller;
+       bss->dpp_controller = conf;
+       return 0;
+fail:
+       os_free(val);
+       os_free(conf);
+       return -1;
+}
+#endif /* CONFIG_DPP2 */
+
+
 static int hostapd_config_fill(struct hostapd_config *conf,
                               struct hostapd_bss_config *bss,
                               const char *buf, char *pos, int line)
@@ -2447,7 +2475,11 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "eapol_version") == 0) {
                int eapol_version = atoi(pos);
 
+#ifdef CONFIG_MACSEC
+               if (eapol_version < 1 || eapol_version > 3) {
+#else /* CONFIG_MACSEC */
                if (eapol_version < 1 || eapol_version > 2) {
+#endif /* CONFIG_MACSEC */
                        wpa_printf(MSG_ERROR,
                                   "Line %d: invalid EAPOL version (%d): '%s'.",
                                   line, eapol_version, pos);
@@ -2470,18 +2502,45 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "server_cert") == 0) {
                os_free(bss->server_cert);
                bss->server_cert = os_strdup(pos);
+       } else if (os_strcmp(buf, "server_cert2") == 0) {
+               os_free(bss->server_cert2);
+               bss->server_cert2 = os_strdup(pos);
        } else if (os_strcmp(buf, "private_key") == 0) {
                os_free(bss->private_key);
                bss->private_key = os_strdup(pos);
+       } else if (os_strcmp(buf, "private_key2") == 0) {
+               os_free(bss->private_key2);
+               bss->private_key2 = os_strdup(pos);
        } else if (os_strcmp(buf, "private_key_passwd") == 0) {
                os_free(bss->private_key_passwd);
                bss->private_key_passwd = os_strdup(pos);
+       } else if (os_strcmp(buf, "private_key_passwd2") == 0) {
+               os_free(bss->private_key_passwd2);
+               bss->private_key_passwd2 = os_strdup(pos);
+       } else if (os_strcmp(buf, "check_cert_subject") == 0) {
+               if (!pos[0]) {
+                       wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'",
+                                  line, pos);
+                       return 1;
+               }
+               os_free(bss->check_cert_subject);
+               bss->check_cert_subject = os_strdup(pos);
+               if (!bss->check_cert_subject)
+                       return 1;
        } else if (os_strcmp(buf, "check_crl") == 0) {
                bss->check_crl = atoi(pos);
+       } else if (os_strcmp(buf, "check_crl_strict") == 0) {
+               bss->check_crl_strict = atoi(pos);
+       } else if (os_strcmp(buf, "crl_reload_interval") == 0) {
+               bss->crl_reload_interval = atoi(pos);
        } else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
                bss->tls_session_lifetime = atoi(pos);
        } else if (os_strcmp(buf, "tls_flags") == 0) {
                bss->tls_flags = parse_tls_flags(pos);
+       } else if (os_strcmp(buf, "max_auth_rounds") == 0) {
+               bss->max_auth_rounds = atoi(pos);
+       } else if (os_strcmp(buf, "max_auth_rounds_short") == 0) {
+               bss->max_auth_rounds_short = atoi(pos);
        } else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
                os_free(bss->ocsp_stapling_response);
                bss->ocsp_stapling_response = os_strdup(pos);
@@ -2494,6 +2553,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "openssl_ciphers") == 0) {
                os_free(bss->openssl_ciphers);
                bss->openssl_ciphers = os_strdup(pos);
+       } else if (os_strcmp(buf, "openssl_ecdh_curves") == 0) {
+               os_free(bss->openssl_ecdh_curves);
+               bss->openssl_ecdh_curves = os_strdup(pos);
        } else if (os_strcmp(buf, "fragment_size") == 0) {
                bss->fragment_size = atoi(pos);
 #ifdef EAP_SERVER_FAST
@@ -2539,6 +2601,24 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
                bss->pac_key_refresh_time = atoi(pos);
 #endif /* EAP_SERVER_FAST */
+#ifdef EAP_SERVER_TEAP
+       } else if (os_strcmp(buf, "eap_teap_auth") == 0) {
+               int val = atoi(pos);
+
+               if (val < 0 || val > 1) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: Invalid eap_teap_auth value",
+                                  line);
+                       return 1;
+               }
+               bss->eap_teap_auth = val;
+       } else if (os_strcmp(buf, "eap_teap_pac_no_inner") == 0) {
+               bss->eap_teap_pac_no_inner = atoi(pos);
+       } else if (os_strcmp(buf, "eap_teap_separate_result") == 0) {
+               bss->eap_teap_separate_result = atoi(pos);
+       } else if (os_strcmp(buf, "eap_teap_id") == 0) {
+               bss->eap_teap_id = atoi(pos);
+#endif /* EAP_SERVER_TEAP */
 #ifdef EAP_SERVER_SIM
        } else if (os_strcmp(buf, "eap_sim_db") == 0) {
                os_free(bss->eap_sim_db);
@@ -2547,6 +2627,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                bss->eap_sim_db_timeout = atoi(pos);
        } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
                bss->eap_sim_aka_result_ind = atoi(pos);
+       } else if (os_strcmp(buf, "eap_sim_id") == 0) {
+               bss->eap_sim_id = atoi(pos);
 #endif /* EAP_SERVER_SIM */
 #ifdef EAP_SERVER_TNC
        } else if (os_strcmp(buf, "tnc") == 0) {
@@ -2584,6 +2666,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "erp_domain") == 0) {
                os_free(bss->erp_domain);
                bss->erp_domain = os_strdup(pos);
+#ifdef CONFIG_WEP
        } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
                int val = atoi(pos);
 
@@ -2611,6 +2694,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                   line, bss->wep_rekeying_period);
                        return 1;
                }
+#endif /* CONFIG_WEP */
        } else if (os_strcmp(buf, "eap_reauth_period") == 0) {
                bss->eap_reauth_period = atoi(pos);
                if (bss->eap_reauth_period < 0) {
@@ -2622,8 +2706,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                bss->eapol_key_index_workaround = atoi(pos);
 #ifdef CONFIG_IAPP
        } else if (os_strcmp(buf, "iapp_interface") == 0) {
-               bss->ieee802_11f = 1;
-               os_strlcpy(bss->iapp_iface, pos, sizeof(bss->iapp_iface));
+               wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
 #endif /* CONFIG_IAPP */
        } else if (os_strcmp(buf, "own_ip_addr") == 0) {
                if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
@@ -2750,6 +2833,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                a = a->next;
                        a->next = attr;
                }
+       } else if (os_strcmp(buf, "radius_req_attr_sqlite") == 0) {
+               os_free(bss->radius_req_attr_sqlite);
+               bss->radius_req_attr_sqlite = os_strdup(pos);
        } else if (os_strcmp(buf, "radius_das_port") == 0) {
                bss->radius_das_port = atoi(pos);
        } else if (os_strcmp(buf, "radius_das_client") == 0) {
@@ -2783,6 +2869,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                }
        } else if (os_strcmp(buf, "wpa") == 0) {
                bss->wpa = atoi(pos);
+       } else if (os_strcmp(buf, "extended_key_id") == 0) {
+               int val = atoi(pos);
+
+               if (bss->extended_key_id < 0 || bss->extended_key_id > 2) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: Invalid extended_key_id=%d; allowed range 0..2",
+                                  line, bss->extended_key_id);
+                       return 1;
+               }
+               bss->extended_key_id = val;
        } else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
                bss->wpa_group_rekey = atoi(pos);
                bss->wpa_group_rekey_set = 1;
@@ -2792,6 +2888,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                bss->wpa_gmk_rekey = atoi(pos);
        } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
                bss->wpa_ptk_rekey = atoi(pos);
+       } else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) {
+               bss->wpa_deny_ptk0_rekey = atoi(pos);
+               if (bss->wpa_deny_ptk0_rekey < 0 ||
+                   bss->wpa_deny_ptk0_rekey > 2) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2",
+                                  line, bss->wpa_deny_ptk0_rekey);
+                       return 1;
+               }
        } else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
                char *endp;
                unsigned long val = strtoul(pos, &endp, 0);
@@ -3044,6 +3149,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                }
        } else if (os_strcmp(buf, "acs_exclude_dfs") == 0) {
                conf->acs_exclude_dfs = atoi(pos);
+       } else if (os_strcmp(buf, "op_class") == 0) {
+               conf->op_class = atoi(pos);
        } else if (os_strcmp(buf, "channel") == 0) {
                if (os_strcmp(pos, "acs_survey") == 0) {
 #ifndef CONFIG_ACS
@@ -3058,21 +3165,35 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                        conf->channel = atoi(pos);
                        conf->acs = conf->channel == 0;
                }
+       } else if (os_strcmp(buf, "edmg_channel") == 0) {
+               conf->edmg_channel = atoi(pos);
+       } else if (os_strcmp(buf, "enable_edmg") == 0) {
+               conf->enable_edmg = atoi(pos);
        } else if (os_strcmp(buf, "chanlist") == 0) {
                if (hostapd_parse_chanlist(conf, pos)) {
                        wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
                                   line);
                        return 1;
                }
+       } else if (os_strcmp(buf, "freqlist") == 0) {
+               if (freq_range_list_parse(&conf->acs_freq_list, pos)) {
+                       wpa_printf(MSG_ERROR, "Line %d: invalid frequency list",
+                                  line);
+                       return 1;
+               }
+               conf->acs_freq_list_present = 1;
+       } else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
+               conf->acs_exclude_6ghz_non_psc = atoi(pos);
        } else if (os_strcmp(buf, "beacon_int") == 0) {
                int val = atoi(pos);
                /* MIB defines range as 1..65535, but very small values
                 * cause problems with the current implementation.
                 * Since it is unlikely that this small numbers are
                 * useful in real life scenarios, do not allow beacon
-                * period to be set below 15 TU. */
-               if (val < 15 || val > 65535) {
-                       wpa_printf(MSG_ERROR, "Line %d: invalid beacon_int %d (expected 15..65535)",
+                * period to be set below 10 TU. */
+               if (val < 10 || val > 65535) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid beacon_int %d (expected 10..65535)",
                                   line, val);
                        return 1;
                }
@@ -3204,6 +3325,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                bss->ignore_broadcast_ssid = atoi(pos);
        } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
                bss->no_probe_resp_if_max_sta = atoi(pos);
+#ifdef CONFIG_WEP
        } else if (os_strcmp(buf, "wep_default_key") == 0) {
                bss->ssid.wep.idx = atoi(pos);
                if (bss->ssid.wep.idx > 3) {
@@ -3222,6 +3344,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                   line, buf);
                        return 1;
                }
+#endif /* CONFIG_WEP */
 #ifndef CONFIG_NO_VLAN
        } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
                bss->ssid.dynamic_vlan = atoi(pos);
@@ -3284,7 +3407,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                }
        } else if (os_strcmp(buf, "use_driver_iface_addr") == 0) {
                conf->use_driver_iface_addr = atoi(pos);
-#ifdef CONFIG_IEEE80211W
        } else if (os_strcmp(buf, "ieee80211w") == 0) {
                bss->ieee80211w = atoi(pos);
        } else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
@@ -3301,6 +3423,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                   line, pos);
                        return 1;
                }
+       } else if (os_strcmp(buf, "beacon_prot") == 0) {
+               bss->beacon_prot = atoi(pos);
        } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
                bss->assoc_sa_query_max_timeout = atoi(pos);
                if (bss->assoc_sa_query_max_timeout == 0) {
@@ -3315,8 +3439,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                   line);
                        return 1;
                }
-#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_IEEE80211N
+#ifdef CONFIG_OCV
+       } else if (os_strcmp(buf, "ocv") == 0) {
+               bss->ocv = atoi(pos);
+               if (bss->ocv && !bss->ieee80211w)
+                       bss->ieee80211w = 1;
+#endif /* CONFIG_OCV */
        } else if (os_strcmp(buf, "ieee80211n") == 0) {
                conf->ieee80211n = atoi(pos);
        } else if (os_strcmp(buf, "ht_capab") == 0) {
@@ -3329,7 +3457,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                conf->require_ht = atoi(pos);
        } else if (os_strcmp(buf, "obss_interval") == 0) {
                conf->obss_interval = atoi(pos);
-#endif /* CONFIG_IEEE80211N */
 #ifdef CONFIG_IEEE80211AC
        } else if (os_strcmp(buf, "ieee80211ac") == 0) {
                conf->ieee80211ac = atoi(pos);
@@ -3362,13 +3489,116 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
                conf->he_phy_capab.he_mu_beamformer = atoi(pos);
        } else if (os_strcmp(buf, "he_bss_color") == 0) {
-               conf->he_op.he_bss_color = atoi(pos);
+               conf->he_op.he_bss_color = atoi(pos) & 0x3f;
+               conf->he_op.he_bss_color_disabled = 0;
+       } else if (os_strcmp(buf, "he_bss_color_partial") == 0) {
+               conf->he_op.he_bss_color_partial = atoi(pos);
        } else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
                conf->he_op.he_default_pe_duration = atoi(pos);
        } else if (os_strcmp(buf, "he_twt_required") == 0) {
                conf->he_op.he_twt_required = atoi(pos);
        } else if (os_strcmp(buf, "he_rts_threshold") == 0) {
                conf->he_op.he_rts_threshold = atoi(pos);
+       } else if (os_strcmp(buf, "he_basic_mcs_nss_set") == 0) {
+               conf->he_op.he_basic_mcs_nss_set = atoi(pos);
+       } else if (os_strcmp(buf, "he_mu_edca_qos_info_param_count") == 0) {
+               conf->he_mu_edca.he_qos_info |=
+                       set_he_cap(atoi(pos), HE_QOS_INFO_EDCA_PARAM_SET_COUNT);
+       } else if (os_strcmp(buf, "he_mu_edca_qos_info_q_ack") == 0) {
+               conf->he_mu_edca.he_qos_info |=
+                       set_he_cap(atoi(pos), HE_QOS_INFO_Q_ACK);
+       } else if (os_strcmp(buf, "he_mu_edca_qos_info_queue_request") == 0) {
+               conf->he_mu_edca.he_qos_info |=
+                       set_he_cap(atoi(pos), HE_QOS_INFO_QUEUE_REQUEST);
+       } else if (os_strcmp(buf, "he_mu_edca_qos_info_txop_request") == 0) {
+               conf->he_mu_edca.he_qos_info |=
+                       set_he_cap(atoi(pos), HE_QOS_INFO_TXOP_REQUEST);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_aifsn") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_acm") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_aci") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmin") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmax") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_be_timer") == 0) {
+               conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_TIMER_IDX] =
+                       atoi(pos) & 0xff;
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_aifsn") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_acm") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_aci") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmin") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmax") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_bk_timer") == 0) {
+               conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_TIMER_IDX] =
+                       atoi(pos) & 0xff;
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_aifsn") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_acm") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_aci") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmin") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmax") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vi_timer") == 0) {
+               conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_TIMER_IDX] =
+                       atoi(pos) & 0xff;
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_aifsn") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_acm") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_aci") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmin") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmax") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |=
+                       set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX);
+       } else if (os_strcmp(buf, "he_mu_edca_ac_vo_timer") == 0) {
+               conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] =
+                       atoi(pos) & 0xff;
+       } else if (os_strcmp(buf, "he_spr_sr_control") == 0) {
+               conf->spr.sr_control = atoi(pos) & 0xff;
+       } else if (os_strcmp(buf, "he_spr_non_srg_obss_pd_max_offset") == 0) {
+               conf->spr.non_srg_obss_pd_max_offset = atoi(pos);
+       } else if (os_strcmp(buf, "he_spr_srg_obss_pd_min_offset") == 0) {
+               conf->spr.srg_obss_pd_min_offset = atoi(pos);
+       } else if (os_strcmp(buf, "he_spr_srg_obss_pd_max_offset") == 0) {
+               conf->spr.srg_obss_pd_max_offset = atoi(pos);
+       } else if (os_strcmp(buf, "he_oper_chwidth") == 0) {
+               conf->he_oper_chwidth = atoi(pos);
+       } else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) {
+               conf->he_oper_centr_freq_seg0_idx = atoi(pos);
+       } else if (os_strcmp(buf, "he_oper_centr_freq_seg1_idx") == 0) {
+               conf->he_oper_centr_freq_seg1_idx = atoi(pos);
 #endif /* CONFIG_IEEE80211AX */
        } else if (os_strcmp(buf, "max_listen_interval") == 0) {
                bss->max_listen_interval = atoi(pos);
@@ -3466,6 +3696,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                }
        } else if (os_strcmp(buf, "wps_cred_processing") == 0) {
                bss->wps_cred_processing = atoi(pos);
+       } else if (os_strcmp(buf, "wps_cred_add_sae") == 0) {
+               bss->wps_cred_add_sae = atoi(pos);
        } else if (os_strcmp(buf, "ap_settings") == 0) {
                os_free(bss->ap_settings);
                bss->ap_settings =
@@ -3475,6 +3707,56 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                   line, pos);
                        return 1;
                }
+       } else if (os_strcmp(buf, "multi_ap_backhaul_ssid") == 0) {
+               size_t slen;
+               char *str = wpa_config_parse_string(pos, &slen);
+
+               if (!str || slen < 1 || slen > SSID_MAX_LEN) {
+                       wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
+                                  line, pos);
+                       os_free(str);
+                       return 1;
+               }
+               os_memcpy(bss->multi_ap_backhaul_ssid.ssid, str, slen);
+               bss->multi_ap_backhaul_ssid.ssid_len = slen;
+               bss->multi_ap_backhaul_ssid.ssid_set = 1;
+               os_free(str);
+       } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_passphrase") == 0) {
+               int len = os_strlen(pos);
+
+               if (len < 8 || len > 63) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid WPA passphrase length %d (expected 8..63)",
+                                  line, len);
+                       return 1;
+               }
+               os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
+               bss->multi_ap_backhaul_ssid.wpa_passphrase = os_strdup(pos);
+               if (bss->multi_ap_backhaul_ssid.wpa_passphrase) {
+                       hostapd_config_clear_wpa_psk(
+                               &bss->multi_ap_backhaul_ssid.wpa_psk);
+                       bss->multi_ap_backhaul_ssid.wpa_passphrase_set = 1;
+               }
+       } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_psk") == 0) {
+               hostapd_config_clear_wpa_psk(
+                       &bss->multi_ap_backhaul_ssid.wpa_psk);
+               bss->multi_ap_backhaul_ssid.wpa_psk =
+                       os_zalloc(sizeof(struct hostapd_wpa_psk));
+               if (!bss->multi_ap_backhaul_ssid.wpa_psk)
+                       return 1;
+               if (hexstr2bin(pos, bss->multi_ap_backhaul_ssid.wpa_psk->psk,
+                              PMK_LEN) ||
+                   pos[PMK_LEN * 2] != '\0') {
+                       wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
+                                  line, pos);
+                       hostapd_config_clear_wpa_psk(
+                               &bss->multi_ap_backhaul_ssid.wpa_psk);
+                       return 1;
+               }
+               bss->multi_ap_backhaul_ssid.wpa_psk->group = 1;
+               os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
+               bss->multi_ap_backhaul_ssid.wpa_passphrase = NULL;
+               bss->multi_ap_backhaul_ssid.wpa_psk_set = 1;
        } else if (os_strcmp(buf, "upnp_iface") == 0) {
                os_free(bss->upnp_iface);
                bss->upnp_iface = os_strdup(pos);
@@ -3498,6 +3780,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "server_id") == 0) {
                os_free(bss->server_id);
                bss->server_id = os_strdup(pos);
+       } else if (os_strcmp(buf, "wps_application_ext") == 0) {
+               wpabuf_free(bss->wps_application_ext);
+               bss->wps_application_ext = wpabuf_parse_bin(pos);
 #ifdef CONFIG_WPS_NFC
        } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
                bss->wps_nfc_dev_pw_id = atoi(pos);
@@ -3817,6 +4102,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "hs20_t_c_server_url") == 0) {
                os_free(bss->t_c_server_url);
                bss->t_c_server_url = os_strdup(pos);
+       } else if (os_strcmp(buf, "hs20_sim_provisioning_url") == 0) {
+               os_free(bss->hs20_sim_provisioning_url);
+               bss->hs20_sim_provisioning_url = os_strdup(pos);
 #endif /* CONFIG_HS20 */
 #ifdef CONFIG_MBO
        } else if (os_strcmp(buf, "mbo") == 0) {
@@ -3898,6 +4186,26 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "sae_commit_override") == 0) {
                wpabuf_free(bss->sae_commit_override);
                bss->sae_commit_override = wpabuf_parse_bin(pos);
+       } else if (os_strcmp(buf, "rsne_override_eapol") == 0) {
+               wpabuf_free(bss->rsne_override_eapol);
+               bss->rsne_override_eapol = wpabuf_parse_bin(pos);
+       } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
+               wpabuf_free(bss->rsnxe_override_eapol);
+               bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
+       } else if (os_strcmp(buf, "rsne_override_ft") == 0) {
+               wpabuf_free(bss->rsne_override_ft);
+               bss->rsne_override_ft = wpabuf_parse_bin(pos);
+       } else if (os_strcmp(buf, "rsnxe_override_ft") == 0) {
+               wpabuf_free(bss->rsnxe_override_ft);
+               bss->rsnxe_override_ft = wpabuf_parse_bin(pos);
+       } else if (os_strcmp(buf, "gtk_rsc_override") == 0) {
+               wpabuf_free(bss->gtk_rsc_override);
+               bss->gtk_rsc_override = wpabuf_parse_bin(pos);
+       } else if (os_strcmp(buf, "igtk_rsc_override") == 0) {
+               wpabuf_free(bss->igtk_rsc_override);
+               bss->igtk_rsc_override = wpabuf_parse_bin(pos);
+       } else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) {
+               bss->no_beacon_rsnxe = atoi(pos);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_SAE
        } else if (os_strcmp(buf, "sae_password") == 0) {
@@ -3926,6 +4234,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                }
        } else if (os_strcmp(buf, "sae_require_mfp") == 0) {
                bss->sae_require_mfp = atoi(pos);
+       } else if (os_strcmp(buf, "sae_confirm_immediate") == 0) {
+               bss->sae_confirm_immediate = atoi(pos);
+       } else if (os_strcmp(buf, "sae_pwe") == 0) {
+               bss->sae_pwe = atoi(pos);
        } else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
                int val = atoi(pos);
                if (val < 0 || val > 255) {
@@ -4075,6 +4387,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "broadcast_deauth") == 0) {
                bss->broadcast_deauth = atoi(pos);
 #ifdef CONFIG_DPP
+       } else if (os_strcmp(buf, "dpp_name") == 0) {
+               os_free(bss->dpp_name);
+               bss->dpp_name = os_strdup(pos);
+       } else if (os_strcmp(buf, "dpp_mud_url") == 0) {
+               os_free(bss->dpp_mud_url);
+               bss->dpp_mud_url = os_strdup(pos);
        } else if (os_strcmp(buf, "dpp_connector") == 0) {
                os_free(bss->dpp_connector);
                bss->dpp_connector = os_strdup(pos);
@@ -4086,6 +4404,11 @@ static int hostapd_config_fill(struct hostapd_config *conf,
        } else if (os_strcmp(buf, "dpp_csign") == 0) {
                if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos))
                        return 1;
+#ifdef CONFIG_DPP2
+       } else if (os_strcmp(buf, "dpp_controller") == 0) {
+               if (hostapd_dpp_controller_parse(bss, pos))
+                       return 1;
+#endif /* CONFIG_DPP2 */
 #endif /* CONFIG_DPP */
 #ifdef CONFIG_OWE
        } else if (os_strcmp(buf, "owe_transition_bssid") == 0) {
@@ -4118,9 +4441,142 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                   line, pos);
                        return 1;
                }
+       } else if (os_strcmp(buf, "owe_ptk_workaround") == 0) {
+               bss->owe_ptk_workaround = atoi(pos);
+#endif /* CONFIG_OWE */
        } else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
                bss->coloc_intf_reporting = atoi(pos);
-#endif /* CONFIG_OWE */
+       } else if (os_strcmp(buf, "multi_ap") == 0) {
+               int val = atoi(pos);
+
+               if (val < 0 || val > 3) {
+                       wpa_printf(MSG_ERROR, "Line %d: Invalid multi_ap '%s'",
+                                  line, buf);
+                       return -1;
+               }
+
+               bss->multi_ap = val;
+       } else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) {
+               conf->rssi_reject_assoc_rssi = atoi(pos);
+       } else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
+               conf->rssi_reject_assoc_timeout = atoi(pos);
+       } else if (os_strcmp(buf, "pbss") == 0) {
+               bss->pbss = atoi(pos);
+#ifdef CONFIG_AIRTIME_POLICY
+       } else if (os_strcmp(buf, "airtime_mode") == 0) {
+               int val = atoi(pos);
+
+               if (val < 0 || val > AIRTIME_MODE_MAX) {
+                       wpa_printf(MSG_ERROR, "Line %d: Unknown airtime_mode",
+                                  line);
+                       return 1;
+               }
+               conf->airtime_mode = val;
+       } else if (os_strcmp(buf, "airtime_update_interval") == 0) {
+               conf->airtime_update_interval = atoi(pos);
+       } else if (os_strcmp(buf, "airtime_bss_weight") == 0) {
+               bss->airtime_weight = atoi(pos);
+       } else if (os_strcmp(buf, "airtime_bss_limit") == 0) {
+               int val = atoi(pos);
+
+               if (val < 0 || val > 1) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: Invalid airtime_bss_limit (must be 0 or 1)",
+                                  line);
+                       return 1;
+               }
+               bss->airtime_limit = val;
+       } else if (os_strcmp(buf, "airtime_sta_weight") == 0) {
+               if (add_airtime_weight(bss, pos) < 0) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: Invalid airtime weight '%s'",
+                                  line, pos);
+                       return 1;
+               }
+#endif /* CONFIG_AIRTIME_POLICY */
+#ifdef CONFIG_MACSEC
+       } else if (os_strcmp(buf, "macsec_policy") == 0) {
+               int macsec_policy = atoi(pos);
+
+               if (macsec_policy < 0 || macsec_policy > 1) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid macsec_policy (%d): '%s'.",
+                                  line, macsec_policy, pos);
+                       return 1;
+               }
+               bss->macsec_policy = macsec_policy;
+       } else if (os_strcmp(buf, "macsec_integ_only") == 0) {
+               int macsec_integ_only = atoi(pos);
+
+               if (macsec_integ_only < 0 || macsec_integ_only > 1) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid macsec_integ_only (%d): '%s'.",
+                                  line, macsec_integ_only, pos);
+                       return 1;
+               }
+               bss->macsec_integ_only = macsec_integ_only;
+       } else if (os_strcmp(buf, "macsec_replay_protect") == 0) {
+               int macsec_replay_protect = atoi(pos);
+
+               if (macsec_replay_protect < 0 || macsec_replay_protect > 1) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid macsec_replay_protect (%d): '%s'.",
+                                  line, macsec_replay_protect, pos);
+                       return 1;
+               }
+               bss->macsec_replay_protect = macsec_replay_protect;
+       } else if (os_strcmp(buf, "macsec_replay_window") == 0) {
+               bss->macsec_replay_window = atoi(pos);
+       } else if (os_strcmp(buf, "macsec_port") == 0) {
+               int macsec_port = atoi(pos);
+
+               if (macsec_port < 1 || macsec_port > 65534) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid macsec_port (%d): '%s'.",
+                                  line, macsec_port, pos);
+                       return 1;
+               }
+               bss->macsec_port = macsec_port;
+       } else if (os_strcmp(buf, "mka_priority") == 0) {
+               int mka_priority = atoi(pos);
+
+               if (mka_priority < 0 || mka_priority > 255) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid mka_priority (%d): '%s'.",
+                                  line, mka_priority, pos);
+                       return 1;
+               }
+               bss->mka_priority = mka_priority;
+       } else if (os_strcmp(buf, "mka_cak") == 0) {
+               size_t len = os_strlen(pos);
+
+               if (len > 2 * MACSEC_CAK_MAX_LEN ||
+                   (len != 2 * 16 && len != 2 * 32) ||
+                   hexstr2bin(pos, bss->mka_cak, len / 2)) {
+                       wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.",
+                                  line, pos);
+                       return 1;
+               }
+               bss->mka_cak_len = len / 2;
+               bss->mka_psk_set |= MKA_PSK_SET_CAK;
+       } else if (os_strcmp(buf, "mka_ckn") == 0) {
+               size_t len = os_strlen(pos);
+
+               if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */
+                   len < 2 || /* too short */
+                   len % 2 != 0 /* not an integral number of bytes */) {
+                       wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
+                                  line, pos);
+                       return 1;
+               }
+               bss->mka_ckn_len = len / 2;
+               if (hexstr2bin(pos, bss->mka_ckn, bss->mka_ckn_len)) {
+                       wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
+                                  line, pos);
+                       return -1;
+               }
+               bss->mka_psk_set |= MKA_PSK_SET_CKN;
+#endif /* CONFIG_MACSEC */
        } else {
                wpa_printf(MSG_ERROR,
                           "Line %d: unknown configuration item '%s'",