/*
* hostapd / Configuration file parser
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
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;
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);
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 "
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;
}
#endif /* CONFIG_NO_VLAN */
-static int hostapd_acl_comp(const void *a, const void *b)
+int hostapd_acl_comp(const void *a, const void *b)
{
const struct mac_acl_entry *aa = a;
const struct mac_acl_entry *bb = b;
}
+int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num,
+ int vlan_id, const u8 *addr)
+{
+ struct mac_acl_entry *newacl;
+
+ newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
+ if (!newacl) {
+ wpa_printf(MSG_ERROR, "MAC list reallocation failed");
+ return -1;
+ }
+
+ *acl = newacl;
+ os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
+ os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id));
+ (*acl)[*num].vlan_id.untagged = vlan_id;
+ (*acl)[*num].vlan_id.notempty = !!vlan_id;
+ (*num)++;
+
+ return 0;
+}
+
+
+void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num,
+ const u8 *addr)
+{
+ int i = 0;
+
+ while (i < *num) {
+ if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) {
+ os_remove_in_array(*acl, *num, sizeof(**acl), i);
+ (*num)--;
+ } else {
+ i++;
+ }
+ }
+}
+
+
static int hostapd_config_read_maclist(const char *fname,
struct mac_acl_entry **acl, int *num)
{
char buf[128], *pos;
int line = 0;
u8 addr[ETH_ALEN];
- struct mac_acl_entry *newacl;
int vlan_id;
f = fopen(fname, "r");
}
while (fgets(buf, sizeof(buf), f)) {
- int i, rem = 0;
+ int rem = 0;
line++;
}
if (rem) {
- i = 0;
- while (i < *num) {
- if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) ==
- 0) {
- os_remove_in_array(*acl, *num,
- sizeof(**acl), i);
- (*num)--;
- } else
- i++;
- }
+ hostapd_remove_acl_mac(acl, num, addr);
continue;
}
vlan_id = 0;
if (*pos != '\0')
vlan_id = atoi(pos);
- newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
- if (newacl == NULL) {
- wpa_printf(MSG_ERROR, "MAC list reallocation failed");
+ if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0) {
fclose(f);
return -1;
}
-
- *acl = newacl;
- os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
- os_memset(&(*acl)[*num].vlan_id, 0,
- sizeof((*acl)[*num].vlan_id));
- (*acl)[*num].vlan_id.untagged = vlan_id;
- (*acl)[*num].vlan_id.notempty = !!vlan_id;
- (*num)++;
}
fclose(f);
#ifdef EAP_SERVER
+
+static int hostapd_config_eap_user_salted(struct hostapd_eap_user *user,
+ const char *hash, size_t len,
+ char **pos, int line,
+ const char *fname)
+{
+ char *pos2 = *pos;
+
+ while (*pos2 != '\0' && *pos2 != ' ' && *pos2 != '\t' && *pos2 != '#')
+ pos2++;
+
+ if (pos2 - *pos < (int) (2 * (len + 1))) { /* at least 1 byte of salt */
+ wpa_printf(MSG_ERROR,
+ "Invalid salted %s hash on line %d in '%s'",
+ hash, line, fname);
+ return -1;
+ }
+
+ user->password = os_malloc(len);
+ if (!user->password) {
+ wpa_printf(MSG_ERROR,
+ "Failed to allocate memory for salted %s hash",
+ hash);
+ return -1;
+ }
+
+ if (hexstr2bin(*pos, user->password, len) < 0) {
+ wpa_printf(MSG_ERROR,
+ "Invalid salted password on line %d in '%s'",
+ line, fname);
+ return -1;
+ }
+ user->password_len = len;
+ *pos += 2 * len;
+
+ user->salt_len = (pos2 - *pos) / 2;
+ user->salt = os_malloc(user->salt_len);
+ if (!user->salt) {
+ wpa_printf(MSG_ERROR,
+ "Failed to allocate memory for salted %s hash",
+ hash);
+ return -1;
+ }
+
+ if (hexstr2bin(*pos, user->salt, user->salt_len) < 0) {
+ wpa_printf(MSG_ERROR,
+ "Invalid salt for password on line %d in '%s'",
+ line, fname);
+ return -1;
+ }
+
+ *pos = pos2;
+ return 0;
+}
+
+
static int hostapd_config_read_eap_user(const char *fname,
struct hostapd_bss_config *conf)
{
user->password_len = 16;
user->password_hash = 1;
pos = pos2;
+ } else if (os_strncmp(pos, "ssha1:", 6) == 0) {
+ pos += 6;
+ if (hostapd_config_eap_user_salted(user, "sha1", 20,
+ &pos,
+ line, fname) < 0)
+ goto failed;
+ } else if (os_strncmp(pos, "ssha256:", 8) == 0) {
+ pos += 8;
+ if (hostapd_config_eap_user_salted(user, "sha256", 32,
+ &pos,
+ line, fname) < 0)
+ goto failed;
+ } else if (os_strncmp(pos, "ssha512:", 8) == 0) {
+ pos += 8;
+ if (hostapd_config_eap_user_salted(user, "sha512", 64,
+ &pos,
+ line, fname) < 0)
+ goto failed;
} else {
pos2 = pos;
while (*pos2 != '\0' && *pos2 != ' ' &&
return ret;
}
+
#endif /* EAP_SERVER */
val |= WPA_KEY_MGMT_FT_PSK;
else if (os_strcmp(start, "FT-EAP") == 0)
val |= WPA_KEY_MGMT_FT_IEEE8021X;
+#ifdef CONFIG_SHA384
+ else if (os_strcmp(start, "FT-EAP-SHA384") == 0)
+ 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)
else if (os_strcmp(start, "DPP") == 0)
val |= WPA_KEY_MGMT_DPP;
#endif /* CONFIG_DPP */
+#ifdef CONFIG_HS20
+ else if (os_strcmp(start, "OSEN") == 0)
+ val |= WPA_KEY_MGMT_OSEN;
+#endif /* CONFIG_HS20 */
else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start);
conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
conf->ht40_plus_minus_allowed = 1;
}
+ 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;
#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)
}
+static int parse_venue_url(struct hostapd_bss_config *bss, char *pos,
+ int line)
+{
+ char *sep;
+ size_t nlen;
+ struct hostapd_venue_url *url;
+ int ret = -1;
+
+ sep = os_strchr(pos, ':');
+ if (!sep)
+ goto fail;
+ *sep++ = '\0';
+
+ nlen = os_strlen(sep);
+ if (nlen > 254)
+ goto fail;
+
+ url = os_realloc_array(bss->venue_url, bss->venue_url_count + 1,
+ sizeof(struct hostapd_venue_url));
+ if (!url)
+ goto fail;
+
+ bss->venue_url = url;
+ url = &bss->venue_url[bss->venue_url_count++];
+
+ url->venue_number = atoi(pos);
+ url->url_len = nlen;
+ os_memcpy(url->url, sep, nlen);
+
+ ret = 0;
+fail:
+ if (ret)
+ wpa_printf(MSG_ERROR, "Line %d: Invalid venue_url '%s'",
+ line, pos);
+ return ret;
+}
+
+
static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf,
int line)
{
}
+static int hs20_parse_osu_nai2(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ os_free(bss->last_osu->osu_nai2);
+ bss->last_osu->osu_nai2 = os_strdup(pos);
+ if (bss->last_osu->osu_nai2 == NULL)
+ return -1;
+ bss->hs20_osu_providers_nai_count++;
+
+ return 0;
+}
+
+
static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
int line)
{
return 0;
}
+
+static int hs20_parse_operator_icon(struct hostapd_bss_config *bss, char *pos,
+ int line)
+{
+ char **n;
+
+ n = os_realloc_array(bss->hs20_operator_icon,
+ bss->hs20_operator_icon_count + 1, sizeof(char *));
+ if (!n)
+ return -1;
+ bss->hs20_operator_icon = n;
+ bss->hs20_operator_icon[bss->hs20_operator_icon_count] = os_strdup(pos);
+ if (!bss->hs20_operator_icon[bss->hs20_operator_icon_count])
+ return -1;
+ bss->hs20_operator_icon_count++;
+
+ return 0;
+}
+
#endif /* CONFIG_HS20 */
{
unsigned int flags = 0;
+ /* Disable TLS v1.3 by default for now to avoid interoperability issue.
+ * This can be enabled by default once the implementation has been fully
+ * completed and tested with other implementations. */
+ flags |= TLS_CONN_DISABLE_TLSv1_3;
+
if (os_strstr(val, "[ALLOW-SIGN-RSA-MD5]"))
flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5;
if (os_strstr(val, "[DISABLE-TIME-CHECKS]"))
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]"))
+ flags &= ~TLS_CONN_DISABLE_TLSv1_3;
if (os_strstr(val, "[SUITEB]"))
flags |= TLS_CONN_SUITEB;
+ if (os_strstr(val, "[SUITEB-NO-ECDH]"))
+ flags |= TLS_CONN_SUITEB_NO_ECDH | TLS_CONN_SUITEB;
return flags;
}
#endif /* EAP_SERVER */
+#ifdef CONFIG_SAE
+static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
+{
+ struct sae_password_entry *pw;
+ const char *pos = val, *pos2, *end = NULL;
+
+ pw = os_zalloc(sizeof(*pw));
+ if (!pw)
+ return -1;
+ os_memset(pw->peer_addr, 0xff, ETH_ALEN); /* default to wildcard */
+
+ pos2 = os_strstr(pos, "|mac=");
+ if (pos2) {
+ end = pos2;
+ pos2 += 5;
+ if (hwaddr_aton(pos2, pw->peer_addr) < 0)
+ goto fail;
+ 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)
+ end = pos2;
+ pos2 += 4;
+ pw->identifier = os_strdup(pos2);
+ if (!pw->identifier)
+ goto fail;
+ }
+
+ if (!end) {
+ pw->password = os_strdup(val);
+ if (!pw->password)
+ goto fail;
+ } else {
+ pw->password = os_malloc(end - val + 1);
+ if (!pw->password)
+ goto fail;
+ os_memcpy(pw->password, val, end - val);
+ pw->password[end - val] = '\0';
+ }
+
+ pw->next = bss->sae_passwords;
+ bss->sae_passwords = pw;
+
+ return 0;
+fail:
+ str_clear_free(pw->password);
+ os_free(pw->identifier);
+ os_free(pw);
+ return -1;
+}
+#endif /* CONFIG_SAE */
+
+
static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss,
const char *buf, char *pos, int line)
bss->private_key_passwd = os_strdup(pos);
} 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) {
} 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
} else if (os_strcmp(buf, "pwd_group") == 0) {
bss->pwd_group = atoi(pos);
#endif /* EAP_SERVER_PWD */
+#ifdef CONFIG_ERP
} else if (os_strcmp(buf, "eap_server_erp") == 0) {
bss->eap_server_erp = atoi(pos);
+#endif /* CONFIG_ERP */
#endif /* EAP_SERVER */
} else if (os_strcmp(buf, "eap_message") == 0) {
char *term;
return 1;
}
bss->wpa_pairwise_update_count = (u32) val;
+ } else if (os_strcmp(buf, "wpa_disable_eapol_key_retries") == 0) {
+ bss->wpa_disable_eapol_key_retries = atoi(pos);
} else if (os_strcmp(buf, "wpa_passphrase") == 0) {
int len = os_strlen(pos);
if (len < 8 || len > 63) {
if (bss->wpa_pairwise &
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
- bss->wpa_pairwise, pos);
+ line, pos);
return 1;
}
} else if (os_strcmp(buf, "rsn_pairwise") == 0) {
if (bss->rsn_pairwise &
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
- bss->rsn_pairwise, pos);
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "group_cipher") == 0) {
+ bss->group_cipher = hostapd_config_parse_cipher(line, pos);
+ if (bss->group_cipher == -1 || bss->group_cipher == 0)
+ return 1;
+ if (bss->group_cipher != WPA_CIPHER_TKIP &&
+ bss->group_cipher != WPA_CIPHER_CCMP &&
+ bss->group_cipher != WPA_CIPHER_GCMP &&
+ bss->group_cipher != WPA_CIPHER_GCMP_256 &&
+ bss->group_cipher != WPA_CIPHER_CCMP_256) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unsupported group cipher suite '%s'",
+ line, pos);
return 1;
}
#ifdef CONFIG_RSN_PREAUTH
os_free(bss->rsn_preauth_interfaces);
bss->rsn_preauth_interfaces = os_strdup(pos);
#endif /* CONFIG_RSN_PREAUTH */
-#ifdef CONFIG_PEERKEY
} else if (os_strcmp(buf, "peerkey") == 0) {
- bss->peerkey = atoi(pos);
-#endif /* CONFIG_PEERKEY */
+ wpa_printf(MSG_INFO,
+ "Line %d: Obsolete peerkey parameter ignored", line);
#ifdef CONFIG_IEEE80211R_AP
} else if (os_strcmp(buf, "mobility_domain") == 0) {
if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
return 1;
}
} else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
+ /* DEPRECATED: Use ft_r0_key_lifetime instead. */
+ bss->r0_key_lifetime = atoi(pos) * 60;
+ } else if (os_strcmp(buf, "ft_r0_key_lifetime") == 0) {
bss->r0_key_lifetime = atoi(pos);
+ } else if (os_strcmp(buf, "r1_max_key_lifetime") == 0) {
+ bss->r1_max_key_lifetime = atoi(pos);
} else if (os_strcmp(buf, "reassociation_deadline") == 0) {
bss->reassociation_deadline = atoi(pos);
} else if (os_strcmp(buf, "rkh_pos_timeout") == 0) {
}
bss->dtim_period = val;
} else if (os_strcmp(buf, "bss_load_update_period") == 0) {
- bss->bss_load_update_period = atoi(pos);
- if (bss->bss_load_update_period < 0 ||
- bss->bss_load_update_period > 100) {
+ int val = atoi(pos);
+
+ if (val < 0 || val > 100) {
wpa_printf(MSG_ERROR,
"Line %d: invalid bss_load_update_period %d",
- line, bss->bss_load_update_period);
+ line, val);
+ return 1;
+ }
+ bss->bss_load_update_period = val;
+ } else if (os_strcmp(buf, "chan_util_avg_period") == 0) {
+ int val = atoi(pos);
+
+ if (val < 0) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid chan_util_avg_period",
+ line);
return 1;
}
+ bss->chan_util_avg_period = val;
} else if (os_strcmp(buf, "rts_threshold") == 0) {
conf->rts_threshold = atoi(pos);
if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) {
line, val);
return 1;
}
- conf->send_probe_response = val;
+ bss->send_probe_response = val;
} else if (os_strcmp(buf, "supported_rates") == 0) {
if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
return 1;
}
#endif /* CONFIG_IEEE80211W */
+#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 */
#ifdef CONFIG_IEEE80211N
} else if (os_strcmp(buf, "ieee80211n") == 0) {
conf->ieee80211n = atoi(pos);
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;
#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);
#ifdef CONFIG_WNM_AP
} else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
bss->wnm_sleep_mode = atoi(pos);
+ } else if (os_strcmp(buf, "wnm_sleep_mode_no_keys") == 0) {
+ bss->wnm_sleep_mode_no_keys = atoi(pos);
} else if (os_strcmp(buf, "bss_transition") == 0) {
bss->bss_transition = atoi(pos);
#endif /* CONFIG_WNM_AP */
} else if (os_strcmp(buf, "venue_name") == 0) {
if (parse_venue_name(bss, pos, line) < 0)
return 1;
+ } else if (os_strcmp(buf, "venue_url") == 0) {
+ if (parse_venue_url(bss, pos, line) < 0)
+ return 1;
} else if (os_strcmp(buf, "network_auth_type") == 0) {
u8 auth_type;
u16 redirect_url_len;
#ifdef CONFIG_HS20
} else if (os_strcmp(buf, "hs20") == 0) {
bss->hs20 = atoi(pos);
+ } else if (os_strcmp(buf, "hs20_release") == 0) {
+ int val = atoi(pos);
+
+ if (val < 1 || val > (HS20_VERSION >> 4) + 1) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Unsupported hs20_release: %s",
+ line, pos);
+ return 1;
+ }
+ bss->hs20_release = val;
} else if (os_strcmp(buf, "disable_dgaf") == 0) {
bss->disable_dgaf = atoi(pos);
} else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
} else if (os_strcmp(buf, "osu_nai") == 0) {
if (hs20_parse_osu_nai(bss, pos, line) < 0)
return 1;
+ } else if (os_strcmp(buf, "osu_nai2") == 0) {
+ if (hs20_parse_osu_nai2(bss, pos, line) < 0)
+ return 1;
} else if (os_strcmp(buf, "osu_method_list") == 0) {
if (hs20_parse_osu_method_list(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "osu_service_desc") == 0) {
if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
return 1;
+ } else if (os_strcmp(buf, "operator_icon") == 0) {
+ if (hs20_parse_operator_icon(bss, pos, line) < 0)
+ return 1;
} else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
os_free(bss->subscr_remediation_url);
bss->subscr_remediation_url = os_strdup(pos);
} else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
bss->subscr_remediation_method = atoi(pos);
+ } else if (os_strcmp(buf, "hs20_t_c_filename") == 0) {
+ os_free(bss->t_c_filename);
+ bss->t_c_filename = os_strdup(pos);
+ } else if (os_strcmp(buf, "hs20_t_c_timestamp") == 0) {
+ bss->t_c_timestamp = strtol(pos, NULL, 0);
+ } 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) {
wpabuf_free(bss->sae_commit_override);
bss->sae_commit_override = wpabuf_parse_bin(pos);
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_SAE
+ } else if (os_strcmp(buf, "sae_password") == 0) {
+ if (parse_sae_password(bss, pos) < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid sae_password",
+ line);
+ return 1;
+ }
+#endif /* CONFIG_SAE */
} else if (os_strcmp(buf, "vendor_elements") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos))
return 1;
return 1;
} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
bss->sae_anti_clogging_threshold = atoi(pos);
+ } else if (os_strcmp(buf, "sae_sync") == 0) {
+ bss->sae_sync = atoi(pos);
} else if (os_strcmp(buf, "sae_groups") == 0) {
if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
wpa_printf(MSG_ERROR,
line, pos);
return 1;
}
+ } else if (os_strcmp(buf, "sae_require_mfp") == 0) {
+ bss->sae_require_mfp = atoi(pos);
} else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
int val = atoi(pos);
if (val < 0 || val > 255) {
} else if (os_strcmp(buf, "dpp_csign") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos))
return 1;
- } else if (os_strcmp(buf, "dpp_csign_expiry") == 0) {
- bss->dpp_csign_expiry = strtol(pos, NULL, 0);
#endif /* CONFIG_DPP */
+#ifdef CONFIG_OWE
+ } else if (os_strcmp(buf, "owe_transition_bssid") == 0) {
+ if (hwaddr_aton(pos, bss->owe_transition_bssid)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid owe_transition_bssid",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "owe_transition_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->owe_transition_ssid, str, slen);
+ bss->owe_transition_ssid_len = slen;
+ os_free(str);
+ } else if (os_strcmp(buf, "owe_transition_ifname") == 0) {
+ os_strlcpy(bss->owe_transition_ifname, pos,
+ sizeof(bss->owe_transition_ifname));
+ } else if (os_strcmp(buf, "owe_groups") == 0) {
+ if (hostapd_parse_intlist(&bss->owe_groups, pos)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid owe_groups value '%s'",
+ line, pos);
+ return 1;
+ }
+ } 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);
} else {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",