path: root/wpa_supplicant
diff options
authorJouni Malinen <jouni@qca.qualcomm.com>2012-12-21 19:35:35 (GMT)
committerJouni Malinen <j@w1.fi>2012-12-21 19:35:35 (GMT)
commit3ab35a660364dc68eaebfc0df6130071bbee6be5 (patch)
tree294c1a72019f93e9d969d11e0ca9db2491f39fa4 /wpa_supplicant
parent318e772ad1ee056b3ed8f5e3fdd4037e01fe3f5e (diff)
Extend EAPOL frames processing workaround for roaming cases
Commit 1ff733383f3d5c73233ef452a738765667021609 added a mechanism to work around issues due to association events and EAPOL RX events being getting reordered. However, this applied only for the case where wpa_supplicant is not in associated state. The same issue can happen in roaming case with drivers that perform BSS selection internally (or in firmware). Handle that case similarly by delaying received EAPOL frame processing if the source address of the EAPOL frame does not match the current BSSID. Since wired IEEE 802.1X do not have BSSID, make this additional workaround conditional on BSSID match having been observed during the previous association. This fixes issues where the initial EAPOL frame after reassociation was either dropped (e.g., due to replay counter not increasing) or replied to with incorrect destination address (the BSSID of the old AP). This can result in significantly more robust roaming behavior with drivers that do not use wpa_supplicant for BSS selection. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'wpa_supplicant')
3 files changed, 20 insertions, 3 deletions
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 68b407b..441718d 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1743,6 +1743,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
+ wpa_s->last_eapol_matches_bssid = 0;
if (wpa_s->pending_eapol_rx) {
struct os_time now, age;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 020f0bd..f033924 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2200,17 +2200,28 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
- if (wpa_s->wpa_state < WPA_ASSOCIATED) {
+ if (wpa_s->wpa_state < WPA_ASSOCIATED ||
+ (wpa_s->last_eapol_matches_bssid &&
+#ifdef CONFIG_AP
+ !wpa_s->ap_iface &&
+#endif /* CONFIG_AP */
+ os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
* There is possible race condition between receiving the
* association event and the EAPOL frame since they are coming
* through different paths from the driver. In order to avoid
* issues in trying to process the EAPOL frame before receiving
* association information, lets queue it for processing until
- * the association event is received.
+ * the association event is received. This may also be needed in
+ * driver-based roaming case, so also use src_addr != BSSID as a
+ * trigger if we have previously confirmed that the
+ * Authenticator uses BSSID as the src_addr (which is not the
+ * case with wired IEEE 802.1X).
wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
- "of received EAPOL frame");
+ "of received EAPOL frame (state=%s bssid=" MACSTR ")",
+ wpa_supplicant_state_txt(wpa_s->wpa_state),
+ MAC2STR(wpa_s->bssid));
wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
if (wpa_s->pending_eapol_rx) {
@@ -2221,6 +2232,9 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
+ wpa_s->last_eapol_matches_bssid =
+ os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 3a56064..07a9e01 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -474,6 +474,7 @@ struct wpa_supplicant {
struct wpabuf *pending_eapol_rx;
struct os_time pending_eapol_rx_time;
u8 pending_eapol_rx_src[ETH_ALEN];
+ unsigned int last_eapol_matches_bssid:1;
struct ibss_rsn *ibss_rsn;