[PATCH 3/3] AP: save eapol for later use (fix EAPOL Start race)
Michal Kazior
michal.kazior
Thu Jul 9 05:26:26 PDT 2015
From: Eliad Peller <eliad at wizery.com>
Some drivers can report TX_STATUS and first EAPOL
Rx in reversed order. This would cause hostap to
drop the EAPOL and delay or fail association.
Cc: Eliad Peller <eliad at wizery.com>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
src/ap/hostapd.c | 3 +++
src/ap/hostapd.h | 5 +++++
src/ap/ieee802_11.c | 40 +++++++++++++++++++++++++++++++++++++---
src/ap/ieee802_1x.c | 11 +++++++++++
4 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 5abe5edd894d..caff2dcf8e41 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -261,6 +261,9 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
os_free(hapd->probereq_cb);
hapd->probereq_cb = NULL;
+ wpabuf_free(hapd->pending_eapol_rx);
+ hapd->pending_eapol_rx = NULL;
+
#ifdef CONFIG_P2P
wpabuf_free(hapd->p2p_beacon_ie);
hapd->p2p_beacon_ie = NULL;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index be5c7a8918d5..b708d98b6ec6 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -177,6 +177,11 @@ struct hostapd_data {
int beacon_set_done;
struct wpabuf *wps_beacon_ie;
struct wpabuf *wps_probe_resp_ie;
+
+ struct wpabuf *pending_eapol_rx;
+ struct os_time pending_eapol_rx_time;
+ u8 pending_eapol_rx_src[ETH_ALEN];
+
#ifdef CONFIG_WPS
unsigned int ap_pin_failures;
unsigned int ap_pin_failures_consecutive;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index cf3567fd3031..c25c777f8ef7 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1563,6 +1563,9 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
static int add_pre_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
+ struct ieee80211_ht_capabilities ht_cap;
+ struct ieee80211_vht_capabilities vht_cap;
+
/*
* Remove the STA entry in order to make sure the STA PS state gets
* cleared and configuration gets updated in case of reassociation back
@@ -1722,7 +1725,7 @@ static void handle_assoc(struct hostapd_data *hapd,
u16 capab_info, listen_interval, seq_ctrl, fc;
u16 resp = WLAN_STATUS_SUCCESS;
const u8 *pos;
- int left, i;
+ int left, i, res;
struct sta_info *sta;
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
@@ -2398,6 +2401,38 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
}
+#define PENDING_EAPOL_TIMEOUT_SEC 1
+
+static void handle_pending_eapol(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *mgmt)
+{
+ struct os_time now, age;
+
+ if (!hapd->pending_eapol_rx)
+ return;
+
+ os_get_time(&now);
+ os_time_sub(&now, &hapd->pending_eapol_rx_time, &age);
+
+ if (age.sec >= PENDING_EAPOL_TIMEOUT_SEC)
+ goto free;
+
+ if (os_memcmp(hapd->pending_eapol_rx_src, mgmt->da, ETH_ALEN))
+ goto free;
+
+ wpa_printf(MSG_DEBUG, "Process pending EAPOL "
+ "frame that was received just before "
+ "association notification");
+ ieee802_1x_receive(hapd, hapd->pending_eapol_rx_src,
+ wpabuf_head(hapd->pending_eapol_rx),
+ wpabuf_len(hapd->pending_eapol_rx));
+
+free:
+ wpabuf_free(hapd->pending_eapol_rx);
+ hapd->pending_eapol_rx = NULL;
+}
+
+
static void handle_assoc_cb(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len, int reassoc, int ok)
@@ -2405,8 +2440,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
u16 status;
struct sta_info *sta;
int new_assoc = 1;
- struct ieee80211_ht_capabilities ht_cap;
- struct ieee80211_vht_capabilities vht_cap;
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
sizeof(mgmt->u.assoc_resp))) {
@@ -2505,6 +2538,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
+ handle_pending_eapol(hapd, mgmt);
}
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index d45b98f1f288..089bebe55591 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -855,6 +855,17 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
"associated/Pre-authenticating STA");
+ if (sta->flags & WLAN_STA_ASSOC_REQ_OK) {
+ wpa_printf(MSG_DEBUG, "Saving EAPOL for later use");
+ wpabuf_free(hapd->pending_eapol_rx);
+ hapd->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
+ if (hapd->pending_eapol_rx) {
+ os_get_time(&hapd->pending_eapol_rx_time);
+ os_memcpy(hapd->pending_eapol_rx_src, sa,
+ ETH_ALEN);
+ }
+ }
+
return;
}
--
2.1.4
More information about the Hostap
mailing list