From patchwork Wed Nov 5 08:50:34 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Peer, Ilan" X-Patchwork-Id: 407022 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) by ozlabs.org (Postfix) with ESMTP id 4BD32140079 for ; Thu, 6 Nov 2014 01:50:05 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 9000117C13D; Wed, 5 Nov 2014 09:50:02 -0500 (EST) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id faLYQwAUr9Mt; Wed, 5 Nov 2014 09:50:02 -0500 (EST) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id CA9F217C144; Wed, 5 Nov 2014 09:49:33 -0500 (EST) X-Original-To: mailman-post+hostap@maxx.shmoo.com Delivered-To: mailman-post+hostap@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 65E6917C11D for ; Wed, 5 Nov 2014 09:49:32 -0500 (EST) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id VypmbWYV+DbX for ; Wed, 5 Nov 2014 09:49:25 -0500 (EST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id D1DDE17C127 for ; Wed, 5 Nov 2014 09:49:16 -0500 (EST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP; 05 Nov 2014 06:42:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,320,1413270000"; d="scan'208";a="617582267" Received: from unknown (HELO ipeer-e6430-3.jer.intel.com) ([10.12.217.164]) by fmsmga001.fm.intel.com with ESMTP; 05 Nov 2014 06:48:29 -0800 From: Ilan Peer To: hostap@lists.shmoo.com Subject: [PATCH] AP: Drop retransmitted auth/assoc frames Date: Wed, 5 Nov 2014 03:50:34 -0500 Message-Id: <1415177437-11016-1-git-send-email-ilan.peer@intel.com> X-Mailer: git-send-email 1.8.3.2 X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.11 Precedence: list List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com 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 --- 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)