diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e5e799d2c..2ea9279fc 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -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; + } } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index d03e9dac0..c68dd825b 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -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); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 63984d8da..e814f86b8 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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