]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Delay processing of EAPOL frames when not associated
authorJouni Malinen <jouni.malinen@atheros.com>
Fri, 4 Sep 2009 15:04:41 +0000 (18:04 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 4 Sep 2009 15:04:41 +0000 (18:04 +0300)
If an EAPOL frame is received while wpa_supplicant thinks the driver is
not associated, queue the frame for processing at the moment when the
association event is received. This is a workaround to a race condition
in receiving data frames and management events from the kernel.

The pending EAPOL frame will not be processed unless an association
event is received within 100 msec for the same BSSID.

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

index e5e799d2c7a0074d0f66c9763d6a2235d6a2dc1a..2ea9279fc47fed15c4a63eac7dae2785b7a2f8f0 100644 (file)
@@ -943,6 +943,25 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
                eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
                eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
        }
+
+       if (wpa_s->pending_eapol_rx) {
+               struct os_time now, age;
+               os_get_time(&now);
+               os_time_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
+               if (age.sec == 0 && age.usec < 100000 &&
+                   os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) ==
+                   0) {
+                       wpa_printf(MSG_DEBUG, "Process pending EAPOL frame "
+                                  "that was received just before association "
+                                  "notification");
+                       wpa_supplicant_rx_eapol(
+                               wpa_s, wpa_s->pending_eapol_rx_src,
+                               wpabuf_head(wpa_s->pending_eapol_rx),
+                               wpabuf_len(wpa_s->pending_eapol_rx));
+               }
+               wpabuf_free(wpa_s->pending_eapol_rx);
+               wpa_s->pending_eapol_rx = NULL;
+       }
 }
 
 
index d03e9dac0ddd72d07b8e435be303644f6e47a907..c68dd825bcb5ca6be278c72858d816cb761f26a3 100644 (file)
@@ -405,6 +405,9 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 
        wpas_wps_deinit(wpa_s);
 
+       wpabuf_free(wpa_s->pending_eapol_rx);
+       wpa_s->pending_eapol_rx = NULL;
+
 #ifdef CONFIG_IBSS_RSN
        ibss_rsn_deinit(wpa_s->ibss_rsn);
        wpa_s->ibss_rsn = NULL;
@@ -1574,6 +1577,27 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
        wpa_printf(MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
        wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
 
+       if (wpa_s->wpa_state < WPA_ASSOCIATED) {
+               /*
+                * 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.
+                */
+               wpa_printf(MSG_DEBUG, "Not associated - Delay processing of "
+                          "received EAPOL frame");
+               wpabuf_free(wpa_s->pending_eapol_rx);
+               wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
+               if (wpa_s->pending_eapol_rx) {
+                       os_get_time(&wpa_s->pending_eapol_rx_time);
+                       os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
+                                 ETH_ALEN);
+               }
+               return;
+       }
+
 #ifdef CONFIG_AP
        if (wpa_s->ap_iface) {
                wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
index 63984d8da0a9a1e8d79990e7a73c4e7077b231ba..e814f86b816005ade0a0d1472886a7f2b11d6fcc 100644 (file)
@@ -364,6 +364,10 @@ struct wpa_supplicant {
        int wps_success; /* WPS success event received */
        int blacklist_cleared;
 
+       struct wpabuf *pending_eapol_rx;
+       struct os_time pending_eapol_rx_time;
+       u8 pending_eapol_rx_src[ETH_ALEN];
+
        struct ibss_rsn *ibss_rsn;
 
 #ifdef CONFIG_SME