#include "common/sae.h"
#include "common/dpp.h"
#include "common/ocv.h"
+#include "common/wpa_common.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "p2p/p2p.h"
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
+ if (hapd->conf->sae_pwe == 1)
+ num++;
if (num > 8) {
/* rest of the rates are encoded in Extended supported
* rates element */
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
+ if (hapd->conf->sae_pwe == 1 && count < 8) {
+ count++;
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ }
+
return pos;
}
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
+ if (hapd->conf->sae_pwe == 1)
+ num++;
if (num <= 8)
return eid;
num -= 8;
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
+ if (hapd->conf->sae_pwe == 1) {
+ count++;
+ if (count > 8)
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ }
+
return pos;
}
const char *password = NULL;
struct sae_password_entry *pw;
const char *rx_id = NULL;
+ int use_pt = 0;
+ struct sae_pt *pt = NULL;
- if (sta->sae->tmp)
+ if (sta->sae->tmp) {
rx_id = sta->sae->tmp->pw_id;
+ use_pt = sta->sae->tmp->h2e;
+ }
for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
if (!is_broadcast_ether_addr(pw->peer_addr) &&
os_strcmp(rx_id, pw->identifier) != 0)
continue;
password = pw->password;
+ pt = pw->pt;
break;
}
- if (!password)
- password = hapd->conf->ssid.wpa_passphrase;
if (!password) {
+ password = hapd->conf->ssid.wpa_passphrase;
+ pt = hapd->conf->ssid.pt;
+ }
+ if (!password || (use_pt && !pt)) {
wpa_printf(MSG_DEBUG, "SAE: No password available");
return NULL;
}
- if (update &&
+ if (update && use_pt &&
+ sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr,
+ NULL) < 0)
+ return NULL;
+
+ if (update && !use_pt &&
sae_prepare_commit(hapd->own_addr, sta->addr,
(u8 *) password, os_strlen(password), rx_id,
sta->sae) < 0) {
{
struct wpabuf *data;
int reply_res;
+ u16 status;
data = auth_build_sae_commit(hapd, sta, update);
if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
if (data == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ status = (sta->sae->tmp && sta->sae->tmp->h2e) ?
+ WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS;
reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
- WLAN_STATUS_SUCCESS, wpabuf_head(data),
+ status, wpabuf_head(data),
wpabuf_len(data), "sae-send-commit");
wpabuf_free(data);
os_memset(¶ms, 0, sizeof(params));
params.status = status;
params.bssid = sta->addr;
- if (status == WLAN_STATUS_SUCCESS && sta->sae)
+ if (status == WLAN_STATUS_SUCCESS && sta->sae &&
+ !hapd->conf->disable_pmksa_caching)
params.pmkid = sta->sae->pmkid;
hostapd_drv_send_external_auth_status(hapd, ¶ms);
static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
- const u8 *bssid, u8 auth_transaction, int allow_reuse,
- int *sta_removed)
+ const u8 *bssid, u16 auth_transaction, u16 status_code,
+ int allow_reuse, int *sta_removed)
{
int ret;
switch (sta->sae->state) {
case SAE_NOTHING:
if (auth_transaction == 1) {
+ if (sta->sae->tmp)
+ sta->sae->tmp->h2e = status_code ==
+ WLAN_STATUS_SAE_HASH_TO_ELEMENT;
ret = auth_sae_send_commit(hapd, sta, bssid,
!allow_reuse);
if (ret)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
/*
- * In mesh case, both Commit and Confirm can be sent
- * immediately. In infrastructure BSS, only a single
- * Authentication frame (Commit) is expected from the AP
- * here and the second one (Confirm) will be sent once
- * the STA has sent its second Authentication frame
- * (Confirm).
+ * In mesh case, both Commit and Confirm are sent
+ * immediately. In infrastructure BSS, by default, only
+ * a single Authentication frame (Commit) is expected
+ * from the AP here and the second one (Confirm) will
+ * be sent once the STA has sent its second
+ * Authentication frame (Confirm). This behavior can be
+ * overridden with explicit configuration so that the
+ * infrastructure BSS case sends both frames together.
*/
- if (hapd->conf->mesh & MESH_ENABLED) {
+ if ((hapd->conf->mesh & MESH_ENABLED) ||
+ hapd->conf->sae_confirm_immediate) {
/*
* Send both Commit and Confirm immediately
* based on SAE finite state machine
* additional events.
*/
return sae_sm_step(hapd, sta, bssid, auth_transaction,
- 0, sta_removed);
+ WLAN_STATUS_SUCCESS, 0, sta_removed);
}
break;
case SAE_CONFIRMED:
}
+static int sae_status_success(struct hostapd_data *hapd, u16 status_code)
+{
+ return (hapd->conf->sae_pwe == 0 &&
+ status_code == WLAN_STATUS_SUCCESS) ||
+ (hapd->conf->sae_pwe == 1 &&
+ status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) ||
+ (hapd->conf->sae_pwe == 2 &&
+ (status_code == WLAN_STATUS_SUCCESS ||
+ status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT));
+}
+
+
+static int sae_is_group_enabled(struct hostapd_data *hapd, int group)
+{
+ int *groups = hapd->conf->sae_groups;
+ int default_groups[] = { 19, 0 };
+ int i;
+
+ if (!groups)
+ groups = default_groups;
+
+ for (i = 0; groups[i] > 0; i++) {
+ if (groups[i] == group)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int check_sae_rejected_groups(struct hostapd_data *hapd,
+ const struct wpabuf *groups)
+{
+ size_t i, count;
+ const u8 *pos;
+
+ if (!groups)
+ return 0;
+
+ pos = wpabuf_head(groups);
+ count = wpabuf_len(groups) / 2;
+ for (i = 0; i < count; i++) {
+ int enabled;
+ u16 group;
+
+ group = WPA_GET_LE16(pos);
+ pos += 2;
+ enabled = sae_is_group_enabled(hapd, group);
+ wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
+ group, enabled ? "enabled" : "disabled");
+ if (enabled)
+ return 1;
+ }
+
+ return 0;
+}
+
+
static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
const struct ieee80211_mgmt *mgmt, size_t len,
u16 auth_transaction, u16 status_code)
#endif /* CONFIG_TESTING_OPTIONS */
if (!sta->sae) {
if (auth_transaction != 1 ||
- status_code != WLAN_STATUS_SUCCESS) {
+ !sae_status_success(hapd, status_code)) {
resp = -1;
goto remove_sta;
}
goto remove_sta;
}
- if (status_code != WLAN_STATUS_SUCCESS)
+ if (!sae_status_success(hapd, status_code))
goto remove_sta;
if (!(hapd->conf->mesh & MESH_ENABLED) &&
resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
((const u8 *) mgmt) + len -
mgmt->u.auth.variable, &token,
- &token_len, groups);
+ &token_len, groups, status_code ==
+ WLAN_STATUS_SAE_HASH_TO_ELEMENT);
if (resp == SAE_SILENTLY_DISCARD) {
wpa_printf(MSG_DEBUG,
"SAE: Drop commit message from " MACSTR " due to reflection attack",
if (resp != WLAN_STATUS_SUCCESS)
goto reply;
+ if (sta->sae->tmp &&
+ check_sae_rejected_groups(
+ hapd, sta->sae->tmp->peer_rejected_groups) < 0) {
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto remove_sta;
+ }
+
if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
wpa_printf(MSG_DEBUG,
"SAE: Request anti-clogging token from "
}
resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
- allow_reuse, &sta_removed);
+ status_code, allow_reuse, &sta_removed);
} else if (auth_transaction == 2) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
}
sta->sae->rc = peer_send_confirm;
}
- resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction, 0,
- &sta_removed);
+ resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
+ status_code, 0, &sta_removed);
} else {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
return WLAN_STATUS_AKMP_NOT_VALID;
if (res == WPA_ALLOC_FAIL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
-#ifdef CONFIG_IEEE80211W
if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
-#endif /* CONFIG_IEEE80211W */
if (res == WPA_INVALID_MDIE)
return WLAN_STATUS_INVALID_MDIE;
if (res == WPA_INVALID_PMKID)
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
hapd->iface->freq,
elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+ elems.rsnxe ? elems.rsnxe - 2 : NULL,
+ elems.rsnxe ? elems.rsnxe_len + 2 : 0,
elems.mdie, elems.mdie_len, NULL, 0);
resp = wpa_res_to_status_code(res);
if (resp != WLAN_STATUS_SUCCESS)
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH |
WLAN_STA_AUTHORIZED);
- if (hostapd_sta_add(hapd, sta->addr, 0, 0, NULL, 0, 0,
- NULL, NULL, sta->flags, 0, 0, 0, 0)) {
+ if (hostapd_sta_add(hapd, sta->addr, 0, 0,
+ sta->supported_rates,
+ sta->supported_rates_len,
+ 0, NULL, NULL, NULL, 0,
+ sta->flags, 0, 0, 0, 0)) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_NOTICE,
return WLAN_STATUS_SUCCESS;
}
+
+u16 owe_validate_request(struct hostapd_data *hapd, const u8 *peer,
+ const u8 *rsn_ie, size_t rsn_ie_len,
+ const u8 *owe_dh, size_t owe_dh_len)
+{
+ struct wpa_ie_data data;
+ int res;
+
+ if (!rsn_ie || rsn_ie_len < 2) {
+ wpa_printf(MSG_DEBUG, "OWE: Invalid RSNE from " MACSTR,
+ MAC2STR(peer));
+ return WLAN_STATUS_INVALID_IE;
+ }
+ rsn_ie -= 2;
+ rsn_ie_len += 2;
+
+ res = wpa_parse_wpa_ie_rsn(rsn_ie, rsn_ie_len, &data);
+ if (res) {
+ wpa_printf(MSG_DEBUG, "Failed to parse RSNE from " MACSTR
+ " (res=%d)", MAC2STR(peer), res);
+ wpa_hexdump(MSG_DEBUG, "RSNE", rsn_ie, rsn_ie_len);
+ return wpa_res_to_status_code(res);
+ }
+ if (!(data.key_mgmt & WPA_KEY_MGMT_OWE)) {
+ wpa_printf(MSG_DEBUG,
+ "OWE: Unexpected key mgmt 0x%x from " MACSTR,
+ (unsigned int) data.key_mgmt, MAC2STR(peer));
+ return WLAN_STATUS_AKMP_NOT_VALID;
+ }
+ if (!owe_dh) {
+ wpa_printf(MSG_DEBUG,
+ "OWE: No Diffie-Hellman Parameter element from "
+ MACSTR, MAC2STR(peer));
+ return WLAN_STATUS_AKMP_NOT_VALID;
+ }
+
+ return WLAN_STATUS_SUCCESS;
+}
+
+
+u16 owe_process_rsn_ie(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ const u8 *rsn_ie, size_t rsn_ie_len,
+ const u8 *owe_dh, size_t owe_dh_len)
+{
+ u16 status;
+ u8 *owe_buf, ie[256 * 2];
+ size_t ie_len = 0;
+ int res;
+
+ if (!rsn_ie || rsn_ie_len < 2) {
+ wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq");
+ status = WLAN_STATUS_INVALID_IE;
+ goto end;
+ }
+
+ if (!sta->wpa_sm)
+ sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr,
+ NULL);
+ if (!sta->wpa_sm) {
+ wpa_printf(MSG_WARNING,
+ "OWE: Failed to initialize WPA state machine");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto end;
+ }
+ rsn_ie -= 2;
+ rsn_ie_len += 2;
+ res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
+ hapd->iface->freq, rsn_ie, rsn_ie_len,
+ NULL, 0, NULL, 0, owe_dh, owe_dh_len);
+ status = wpa_res_to_status_code(res);
+ if (status != WLAN_STATUS_SUCCESS)
+ goto end;
+ status = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
+ if (status != WLAN_STATUS_SUCCESS)
+ goto end;
+ owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, ie, sizeof(ie),
+ NULL, 0);
+ if (!owe_buf) {
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto end;
+ }
+
+ if (sta->owe_ecdh) {
+ struct wpabuf *pub;
+
+ pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
+ if (!pub) {
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto end;
+ }
+
+ /* OWE Diffie-Hellman Parameter element */
+ *owe_buf++ = WLAN_EID_EXTENSION; /* Element ID */
+ *owe_buf++ = 1 + 2 + wpabuf_len(pub); /* Length */
+ *owe_buf++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension
+ */
+ WPA_PUT_LE16(owe_buf, sta->owe_group);
+ owe_buf += 2;
+ os_memcpy(owe_buf, wpabuf_head(pub), wpabuf_len(pub));
+ owe_buf += wpabuf_len(pub);
+ wpabuf_free(pub);
+ sta->external_dh_updated = 1;
+ }
+ ie_len = owe_buf - ie;
+
+end:
+ wpa_printf(MSG_DEBUG, "OWE: Update status %d, ie len %d for peer "
+ MACSTR, status, (unsigned int) ie_len,
+ MAC2STR(sta->addr));
+ hostapd_drv_update_dh_ie(hapd, sta->addr, status,
+ status == WLAN_STATUS_SUCCESS ? ie : NULL,
+ ie_len);
+
+ return status;
+}
+
#endif /* CONFIG_OWE */
return resp;
}
#endif /* CONFIG_IEEE80211AC */
+#ifdef CONFIG_IEEE80211AX
+ if (hapd->iconf->ieee80211ax) {
+ resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP,
+ elems.he_capabilities,
+ elems.he_capabilities_len);
+ if (resp != WLAN_STATUS_SUCCESS)
+ return resp;
+ }
+#endif /* CONFIG_IEEE80211AX */
#ifdef CONFIG_P2P
if (elems.p2p) {
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
hapd->iface->freq,
wpa_ie, wpa_ie_len,
+ elems.rsnxe ? elems.rsnxe - 2 : NULL,
+ elems.rsnxe ? elems.rsnxe_len + 2 : 0,
elems.mdie, elems.mdie_len,
elems.owe_dh, elems.owe_dh_len);
resp = wpa_res_to_status_code(res);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
-#ifdef CONFIG_IEEE80211W
if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
(WLAN_STA_ASSOC | WLAN_STA_MFP) &&
!sta->sa_query_timed_out &&
sta->flags |= WLAN_STA_MFP;
else
sta->flags &= ~WLAN_STA_MFP;
-#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R_AP
if (sta->auth_alg == WLAN_AUTH_FT) {
sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
elems.hs20_len - 4);
release = ((elems.hs20[4] >> 4) & 0x0f) + 1;
- if (release >= 2 && !wpa_auth_uses_mfp(sta->wpa_sm)) {
+ if (release >= 2 && !wpa_auth_uses_mfp(sta->wpa_sm) &&
+ hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
wpa_printf(MSG_DEBUG,
"HS 2.0: PMF not negotiated by release %d station "
MACSTR, release, MAC2STR(sta->addr));
{
struct ieee80211_ht_capabilities ht_cap;
struct ieee80211_vht_capabilities vht_cap;
+ struct ieee80211_he_capabilities he_cap;
int set = 1;
/*
if (sta->flags & WLAN_STA_VHT)
hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
#endif /* CONFIG_IEEE80211AC */
+#ifdef CONFIG_IEEE80211AX
+ if (sta->flags & WLAN_STA_HE) {
+ hostapd_get_he_capab(hapd, sta->he_capab, &he_cap,
+ sta->he_capab_len);
+ }
+#endif /* CONFIG_IEEE80211AX */
/*
* Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
sta->listen_interval,
sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
+ sta->flags & WLAN_STA_HE ? &he_cap : NULL,
+ sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0,
sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
sta->vht_opmode, sta->p2p_ie ? 1 : 0,
set)) {
ies, ies_len);
#endif /* CONFIG_OWE */
-#ifdef CONFIG_IEEE80211W
if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
-#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211N
p = hostapd_eid_ht_capabilities(hapd, p);
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
- if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
+ if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
+ !is_6ghz_op_class(hapd->iconf->op_class)) {
u32 nsts = 0, sta_nsts;
if (sta && hapd->conf->use_sta_nsts && sta->vht_capabilities) {
}
#endif /* CONFIG_IEEE80211AC */
+#ifdef CONFIG_IEEE80211AX
+ if (hapd->iconf->ieee80211ax) {
+ p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP);
+ p = hostapd_eid_he_operation(hapd, p);
+ p = hostapd_eid_spatial_reuse(hapd, p);
+ p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
+ }
+#endif /* CONFIG_IEEE80211AX */
+
p = hostapd_eid_ext_capab(hapd, p);
p = hostapd_eid_bss_max_idle_period(hapd, p);
if (sta && sta->qos_map_enabled)
return owe_buf;
}
+ if (sta->owe_pmk && sta->external_dh_updated) {
+ wpa_printf(MSG_DEBUG, "OWE: Using previously derived PMK");
+ *reason = WLAN_STATUS_SUCCESS;
+ return owe_buf;
+ }
+
*reason = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
if (*reason != WLAN_STATUS_SUCCESS)
return NULL;
*/
sta->flags |= WLAN_STA_ASSOC_REQ_OK;
-#ifdef CONFIG_IEEE80211W
if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
"SA Query procedure", reassoc ? "re" : "");
* trying to associate.
*/
}
-#endif /* CONFIG_IEEE80211W */
/* Make sure that the previously registered inactivity timer will not
* remove the STA immediately. */
}
-#ifdef CONFIG_IEEE80211W
static int robust_action_frame(u8 category)
{
return category != WLAN_ACTION_PUBLIC &&
category != WLAN_ACTION_HT;
}
-#endif /* CONFIG_IEEE80211W */
static int handle_action(struct hostapd_data *hapd,
return 0;
}
-#ifdef CONFIG_IEEE80211W
if (sta && (sta->flags & WLAN_STA_MFP) &&
!(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
robust_action_frame(mgmt->u.action.category)) {
"an MFP STA");
return 0;
}
-#endif /* CONFIG_IEEE80211W */
if (sta) {
u16 fc = le_to_host16(mgmt->frame_control);
case WLAN_ACTION_WMM:
hostapd_wmm_action(hapd, mgmt, len);
return 1;
-#ifdef CONFIG_IEEE80211W
case WLAN_ACTION_SA_QUERY:
ieee802_11_sa_query_action(hapd, mgmt, len);
return 1;
-#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WNM_AP
case WLAN_ACTION_WNM:
ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
fc = le_to_host16(mgmt->frame_control);
stype = WLAN_FC_GET_STYPE(fc);
+ if (is_multicast_ether_addr(mgmt->sa) ||
+ is_zero_ether_addr(mgmt->sa) ||
+ os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
+ /* Do not process any frames with unexpected/invalid SA so that
+ * we do not add any state for unexpected STA addresses or end
+ * up sending out frames to unexpected destination. */
+ wpa_printf(MSG_DEBUG, "MGMT: Invalid SA=" MACSTR
+ " in received frame - ignore this frame silently",
+ MAC2STR(mgmt->sa));
+ return 0;
+ }
+
if (stype == WLAN_FC_STYPE_BEACON) {
handle_beacon(hapd, mgmt, len, fi);
return 1;
else
mlme_associate_indication(hapd, sta);
-#ifdef CONFIG_IEEE80211W
sta->sa_query_timed_out = 0;
-#endif /* CONFIG_IEEE80211W */
if (sta->eapol_sm == NULL) {
/*
wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
MACSTR, MAC2STR(src));
- if (is_multicast_ether_addr(src)) {
- /* Broadcast bit set in SA?! Ignore the frame silently. */
+ if (is_multicast_ether_addr(src) || is_zero_ether_addr(src) ||
+ os_memcmp(src, hapd->own_addr, ETH_ALEN) == 0) {
+ /* Broadcast bit set in SA or unexpected SA?! Ignore the frame
+ * silently. */
return;
}