]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Extend EAPOL frames processing workaround for roaming cases
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 21 Dec 2012 19:35:35 +0000 (21:35 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 21 Dec 2012 19:35:35 +0000 (21:35 +0200)
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>

wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 68b407b9a35a838611ea1cc7af46e1a6817736b4..441718d7f10b0675e2b5700e9ab579354d769819 100644 (file)
@@ -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;
                os_get_time(&now);
index 020f0bd3a54a630f56537489e1a662da8c142305..f033924cb33dabbc14b8a0458b0036b766d77716 100644 (file)
@@ -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));
                wpabuf_free(wpa_s->pending_eapol_rx);
                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,
                return;
        }
 
+       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);
index 3a56064b056c05ed92d27f680ea5bf1e24d23c19..07a9e01d643513d3bceafd505950adbed0c060fc 100644 (file)
@@ -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;