Extend EAPOL frames processing workaround for roaming cases

Commit 1ff733383f 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>
This commit is contained in:
Jouni Malinen 2012-12-21 21:35:35 +02:00 committed by Jouni Malinen
parent 318e772ad1
commit 3ab35a6603
3 changed files with 20 additions and 3 deletions

View 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); eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
} }
wpa_s->last_eapol_matches_bssid = 0;
if (wpa_s->pending_eapol_rx) { if (wpa_s->pending_eapol_rx) {
struct os_time now, age; struct os_time now, age;
os_get_time(&now); os_get_time(&now);

View 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_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len); 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 * There is possible race condition between receiving the
* association event and the EAPOL frame since they are coming * association event and the EAPOL frame since they are coming
* through different paths from the driver. In order to avoid * through different paths from the driver. In order to avoid
* issues in trying to process the EAPOL frame before receiving * issues in trying to process the EAPOL frame before receiving
* association information, lets queue it for processing until * 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 " 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); wpabuf_free(wpa_s->pending_eapol_rx);
wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len); wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
if (wpa_s->pending_eapol_rx) { if (wpa_s->pending_eapol_rx) {
@ -2221,6 +2232,9 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
return; return;
} }
wpa_s->last_eapol_matches_bssid =
os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
#ifdef CONFIG_AP #ifdef CONFIG_AP
if (wpa_s->ap_iface) { if (wpa_s->ap_iface) {
wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len); wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);

View file

@ -474,6 +474,7 @@ struct wpa_supplicant {
struct wpabuf *pending_eapol_rx; struct wpabuf *pending_eapol_rx;
struct os_time pending_eapol_rx_time; struct os_time pending_eapol_rx_time;
u8 pending_eapol_rx_src[ETH_ALEN]; u8 pending_eapol_rx_src[ETH_ALEN];
unsigned int last_eapol_matches_bssid:1;
struct ibss_rsn *ibss_rsn; struct ibss_rsn *ibss_rsn;