#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)
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]"))
#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)
{
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)
#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)
} 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, "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) {
* 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;
}
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_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);
}
} 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 =
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);
} 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) {
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 */
} else {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",