[PATCH] AP: Drop retransmitted auth/assoc frames
Ilan Peer
ilan.peer
Wed Nov 5 00:50:34 PST 2014
It is possible that a station device might miss an ACK for
an authentication or association frame, and thus retransmit the
same frame although the frame is already being processed in the stack.
In such a case, the local AP will process the retransmitted frame although
it has already handled the request, which might cause the station to get
confused and as a result disconnect from the AP, blacklist it etc.
To avoid such a case, save the sequence control of the last processed
management frame and in case of retransmissions drop them.
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
src/ap/ieee802_11.c | 46 +++++++++++++++++++++++++++++++++++++++-----
src/ap/sta_info.c | 2 ++
src/ap/sta_info.h | 3 +++
src/common/ieee802_11_defs.h | 2 ++
4 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index d59a2b4..bb887e9 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -560,6 +560,7 @@ static void handle_auth(struct hostapd_data *hapd,
size_t resp_ies_len = 0;
char *identity = NULL;
char *radius_cui = NULL;
+ u16 seq_ctrl;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
@@ -581,6 +582,7 @@ static void handle_auth(struct hostapd_data *hapd,
auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
status_code = le_to_host16(mgmt->u.auth.status_code);
fc = le_to_host16(mgmt->frame_control);
+ seq_ctrl = le_to_host16(mgmt->seq_ctrl);
if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
2 + WLAN_AUTH_CHALLENGE_LEN &&
@@ -653,10 +655,25 @@ static void handle_auth(struct hostapd_data *hapd,
return;
}
- sta = ap_sta_add(hapd, mgmt->sa);
- if (!sta) {
- resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
- goto fail;
+ sta = ap_get_sta(hapd, mgmt->sa);
+ if (sta) {
+ if ((fc & WLAN_FC_RETRY) &&
+ (sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ) &&
+ (sta->last_seq_ctrl == seq_ctrl)) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "Dropping repeated authentication frame seq_ctrl=%d",
+ seq_ctrl);
+ return;
+ }
+ } else {
+ sta = ap_sta_add(hapd, mgmt->sa);
+ if (!sta) {
+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+ goto fail;
+ }
+ sta->last_seq_ctrl = seq_ctrl;
}
if (vlan_id > 0) {
@@ -1291,7 +1308,7 @@ static void handle_assoc(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len,
int reassoc)
{
- u16 capab_info, listen_interval;
+ u16 capab_info, listen_interval, seq_ctrl, fc;
u16 resp = WLAN_STATUS_SUCCESS;
const u8 *pos;
int left, i;
@@ -1345,6 +1362,8 @@ static void handle_assoc(struct hostapd_data *hapd,
left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
pos = mgmt->u.assoc_req.variable;
}
+ fc = le_to_host16(mgmt->frame_control);
+ seq_ctrl = le_to_host16(mgmt->seq_ctrl);
sta = ap_get_sta(hapd, mgmt->sa);
#ifdef CONFIG_IEEE80211R
@@ -1367,6 +1386,18 @@ static void handle_assoc(struct hostapd_data *hapd,
return;
}
+ if (sta->flags == WLAN_STA_AUTH) {
+ sta->last_seq_ctrl = seq_ctrl;
+ } else if ((fc & WLAN_FC_RETRY) &&
+ (sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ) &&
+ (sta->last_seq_ctrl == seq_ctrl)) {
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "Dropping repeated association frame seq_ctrl=%d",
+ seq_ctrl);
+ return;
+ }
+
if (hapd->tkip_countermeasures) {
resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
goto fail;
@@ -1492,6 +1523,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
}
ap_sta_set_authorized(hapd, sta, 0);
+ sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
@@ -1543,6 +1575,7 @@ static void handle_deauth(struct hostapd_data *hapd,
}
ap_sta_set_authorized(hapd, sta, 0);
+ sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
WLAN_STA_ASSOC_REQ_OK);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
@@ -1877,6 +1910,7 @@ static void handle_auth_cb(struct hostapd_data *hapd,
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "authenticated");
sta->flags |= WLAN_STA_AUTH;
+ sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
}
}
@@ -1945,6 +1979,8 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
if (status != WLAN_STATUS_SUCCESS)
return;
+ sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
+
/* Stop previous accounting session, if one is started, and allocate
* new session id for the new session. */
accounting_sta_stop(hapd, sta);
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index ec0e493..aae6b14 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -600,6 +600,7 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
sta->ssid = &hapd->conf->ssid;
ap_sta_remove_in_other_bss(hapd, sta);
+ sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
return sta;
}
@@ -663,6 +664,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
{
wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
+ sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_DEAUTH;
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 25edd7f..ec195f0 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -152,6 +152,9 @@ struct sta_info {
#endif /* CONFIG_SAE */
u32 session_timeout; /* valid only if session_timeout_set == 1 */
+
+ /* last auth/assoc seq. control */
+ u16 last_seq_ctrl;
};
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index f5adbc0..5ea4a9d 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -25,6 +25,8 @@
#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2)
#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4)
+#define WLAN_INVALID_MGMT_SEQ 0xFFFF
+
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
#define WLAN_GET_SEQ_SEQ(seq) \
(((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4)
--
1.8.3.2
More information about the Hostap
mailing list