diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c index 093383b0b4..350d4c7a29 100644 --- a/core/dp/txrx/ol_rx.c +++ b/core/dp/txrx/ol_rx.c @@ -1198,6 +1198,11 @@ void ol_rx_peer_init(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer) peer->security[txrx_sec_ucast].sec_type = peer->security[txrx_sec_mcast].sec_type = htt_sec_type_none; peer->keyinstalled = 0; + + peer->last_assoc_rcvd = 0; + peer->last_disassoc_rcvd = 0; + peer->last_deauth_rcvd = 0; + qdf_atomic_init(&peer->fw_pn_check); } @@ -1205,6 +1210,9 @@ void ol_rx_peer_cleanup(struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer) { peer->keyinstalled = 0; + peer->last_assoc_rcvd = 0; + peer->last_disassoc_rcvd = 0; + peer->last_deauth_rcvd = 0; ol_rx_reorder_peer_cleanup(vdev, peer); } diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index 43e2461a91..a36346e63f 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -1000,6 +1000,9 @@ struct ol_txrx_peer_t { uint32_t last_pkt_tsf; uint8_t last_pkt_tid; uint16_t last_pkt_center_freq; + qdf_time_t last_assoc_rcvd; + qdf_time_t last_disassoc_rcvd; + qdf_time_t last_deauth_rcvd; }; enum ol_rx_err_type { diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index 0622887c16..e66de6befd 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -160,10 +160,6 @@ void lim_send_heart_beat_timeout_ind(tpAniSirGlobal pMac, tpPESession psessionEn tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, uint32_t subType); -bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info); -#ifdef WLAN_FEATURE_11W -bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info); -#endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx, struct sSirSmeRoamOffloadSynchInd *roam_sync_ind_ptr, diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 176a318dee..5912165c93 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1131,134 +1131,6 @@ uint8_t lim_is_system_in_scan_state(tpAniSirGlobal pMac) } } /*** end lim_is_system_in_scan_state() ***/ -#ifdef WLAN_FEATURE_11W -/** - * lim_is_assoc_req_for_drop()- function to decides to drop assoc\reassoc - * frames. - * @mac: pointer to global mac structure - * @rx_pkt_info: rx packet meta information - * - * This function is called before enqueuing the frame to PE queue to - * drop flooded assoc/reassoc frames getting into PE Queue. - * - * Return: true for dropping the frame otherwise false - */ - -bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info) -{ - uint8_t session_id; - uint16_t aid; - tpPESession session_entry; - tpSirMacMgmtHdr mac_hdr; - tpDphHashNode sta_ds; - - mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); - session_entry = pe_find_session_by_bssid(mac, mac_hdr->bssId, - &session_id); - if (!session_entry) { - PELOG1(limLog(pMac, LOG1, - FL("session does not exist for given STA [%pM]"), - mac_hdr->sa);); - return false; - } - - sta_ds = dph_lookup_hash_entry(mac, mac_hdr->sa, &aid, - &session_entry->dph.dphHashTable); - if (!sta_ds) { - PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL"));); - return false; - } - - if (!sta_ds->rmfEnabled) - return false; - - if (sta_ds->pmfSaQueryState == DPH_SA_QUERY_IN_PROGRESS) - return true; - - if (sta_ds->last_assoc_received_time && - ((qdf_mc_timer_get_system_ticks() - - sta_ds->last_assoc_received_time) < 1000)) - return true; - - sta_ds->last_assoc_received_time = qdf_mc_timer_get_system_ticks(); - return false; -} -#endif - -/** - * lim_is_deauth_diassoc_for_drop()- function to decides to drop deauth\diassoc - * frames. - * @mac: pointer to global mac structure - * @rx_pkt_info: rx packet meta information - * - * This function is called before enqueuing the frame to PE queue to - * drop flooded deauth/diassoc frames getting into PE Queue. - * - * Return: true for dropping the frame otherwise false - */ - -bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info) -{ - uint8_t session_id; - uint16_t aid; - tpPESession session_entry; - tpSirMacMgmtHdr mac_hdr; - tpDphHashNode sta_ds; - - mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); - session_entry = pe_find_session_by_bssid(mac, mac_hdr->bssId, - &session_id); - if (!session_entry) { - PELOG1(limLog(mac, LOG1, - FL("session does not exist for given STA [%pM]"), - mac_hdr->sa);); - return true; - } - - sta_ds = dph_lookup_hash_entry(mac, mac_hdr->sa, &aid, - &session_entry->dph.dphHashTable); - if (!sta_ds) { - PELOG1(limLog(mac, LOG1, FL("pStaDs is NULL"));); - return true; - } - -#ifdef WLAN_FEATURE_11W - if (session_entry->limRmfEnabled) { - if ((WMA_GET_RX_DPU_FEEDBACK(rx_pkt_info) & - DPU_FEEDBACK_UNPROTECTED_ERROR)) { - /* It may be possible that deauth/diassoc frames from a - * spoofy AP is received. So if all further - * deauth/diassoc frmaes are dropped, then it may - * result in lossing deauth/diassoc frames from genuine - * AP. So process all deauth/diassoc frames with - * a time difference of 1 sec. - */ - if ((qdf_mc_timer_get_system_ticks() - - sta_ds->last_unprot_deauth_disassoc) < 1000) - return true; - - sta_ds->last_unprot_deauth_disassoc = - qdf_mc_timer_get_system_ticks(); - } else { - /* PMF enabed, Management frames are protected */ - if (sta_ds->proct_deauh_disassoc_cnt) - return true; - else - sta_ds->proct_deauh_disassoc_cnt++; - } - } else -#endif - /* PMF disabled */ - { - if (sta_ds->is_disassoc_deauth_in_progress) - return true; - else - sta_ds->is_disassoc_deauth_in_progress++; - } - - return false; -} - /** *\brief lim_received_hb_handler() * @@ -2209,18 +2081,6 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(tpAniSirGlobal pMac, } } - if ((subType == SIR_MAC_MGMT_DEAUTH || - subType == SIR_MAC_MGMT_DISASSOC) && - lim_is_deauth_diassoc_for_drop(pMac, pRxPacketInfo)) - return eMGMT_DROP_SPURIOUS_FRAME; - -#ifdef WLAN_FEATURE_11W - if ((subType == SIR_MAC_MGMT_ASSOC_REQ || - subType == SIR_MAC_MGMT_REASSOC_REQ) && - lim_is_assoc_req_for_drop(pMac, pRxPacketInfo)) - return eMGMT_DROP_SPURIOUS_FRAME; -#endif - framelen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index 884b2050a8..27d6a41597 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -803,6 +803,17 @@ lim_handle80211_frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, uint8_t *pDeferMsg isFrmFt = WMA_GET_RX_FT_DONE(pRxPacketInfo); fc = pHdr->fc; + if (pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) { + psessionEntry = pe_find_session_by_bssid(pMac, + pHdr->bssId, &sessionId); + if (psessionEntry && + (QDF_SAP_MODE == psessionEntry->pePersona)) { + lim_log(pMac, LOG1, + FL("CAC timer running - drop the frame")); + goto end; + } + } + #ifdef WLAN_DUMP_MGMTFRAMES lim_log(pMac, LOGE, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), diff --git a/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c b/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c index 057de0544b..a337ec605c 100644 --- a/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c +++ b/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c @@ -109,9 +109,6 @@ sys_bbt_process_message_core(tpAniSirGlobal mac_ctx, tpSirMsgQ msg, cds_pkt_t *vos_pkt = (cds_pkt_t *) msg->bodyptr; QDF_STATUS qdf_status = wma_ds_peek_rx_packet_info(vos_pkt, &bd_ptr, false); - uint8_t sessionid; - tpPESession pe_session; - tpSirMacMgmtHdr mac_hdr; mac_ctx->sys.gSysBbtReceived++; @@ -130,19 +127,7 @@ sys_bbt_process_message_core(tpAniSirGlobal mac_ctx, tpSirMsgQ msg, framecount = mac_ctx->sys.gSysFrameCount[type][subtype]; if (type == SIR_MAC_MGMT_FRAME) { - if (true == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) { - mac_hdr = WMA_GET_RX_MAC_HEADER(bd_ptr); - pe_session = pe_find_session_by_bssid(mac_ctx, - mac_hdr->bssId, - &sessionid); - if (pe_session && - (pe_session->pePersona == QDF_SAP_MODE)) { - QDF_TRACE(QDF_MODULE_ID_SYS, - QDF_TRACE_LEVEL_INFO_HIGH, - FL("CAC timer is running, dropping the mgmt frame")); - goto fail; - } - } + tpSirMacMgmtHdr mac_hdr; /* * Drop beacon frames in deferred state to avoid VOSS run out of @@ -169,27 +154,26 @@ sys_bbt_process_message_core(tpAniSirGlobal mac_ctx, tpSirMsgQ msg, goto fail; } + mac_hdr = WMA_GET_RX_MAC_HEADER(bd_ptr); + if (subtype == SIR_MAC_MGMT_ASSOC_REQ) { + sys_log(mac_ctx, LOG1, + FL("ASSOC REQ frame allowed: da: " MAC_ADDRESS_STR ", sa: " MAC_ADDRESS_STR ", bssid: " MAC_ADDRESS_STR ", Assoc Req count so far: %d\n"), + MAC_ADDR_ARRAY(mac_hdr->da), + MAC_ADDR_ARRAY(mac_hdr->sa), + MAC_ADDR_ARRAY(mac_hdr->bssId), + mac_ctx->sys.gSysFrameCount[type][subtype]); + } if (subtype == SIR_MAC_MGMT_DEAUTH) { - tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(bd_ptr); - sys_log(mac_ctx, LOGE, - FL("DEAUTH frame allowed: " - "da: " MAC_ADDRESS_STR ", " - "sa: " MAC_ADDRESS_STR ", " - "bssid: " MAC_ADDRESS_STR ", " - "DEAUTH count so far: %d\n"), + sys_log(mac_ctx, LOG1, + FL("DEAUTH frame allowed: da: " MAC_ADDRESS_STR ", sa: " MAC_ADDRESS_STR ", bssid: " MAC_ADDRESS_STR ", DEAUTH count so far: %d\n"), MAC_ADDR_ARRAY(mac_hdr->da), MAC_ADDR_ARRAY(mac_hdr->sa), MAC_ADDR_ARRAY(mac_hdr->bssId), mac_ctx->sys.gSysFrameCount[type][subtype]); } if (subtype == SIR_MAC_MGMT_DISASSOC) { - tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(bd_ptr); - sys_log(mac_ctx, LOGE, - FL("DISASSOC frame allowed: " - "da: " MAC_ADDRESS_STR ", " - "sa: " MAC_ADDRESS_STR ", " - "bssid: " MAC_ADDRESS_STR ", " - "DISASSOC count so far: %d\n"), + sys_log(mac_ctx, LOG1, + FL("DISASSOC frame allowed: da: " MAC_ADDRESS_STR ", sa: " MAC_ADDRESS_STR ", bssid: " MAC_ADDRESS_STR ", DISASSOC count so far: %d\n"), MAC_ADDR_ARRAY(mac_hdr->da), MAC_ADDR_ARRAY(mac_hdr->sa), MAC_ADDR_ARRAY(mac_hdr->bssId), diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 6d2dd9acb7..42c2c9d6fe 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -119,6 +119,9 @@ #define MAX_ENTRY_HOLD_REQ_QUEUE 2 #define MAX_ENTRY_VDEV_RESP_QUEUE 10 +/* Time(in ms) to detect DOS attack */ +#define WMA_MGMT_FRAME_DETECT_DOS_TIMER 1000 + /** * struct index_data_rate_type - non vht data rate type * @mcs_index: mcs rate index diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 38dcfaf93b..6a2ddde6bd 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -2858,6 +2858,96 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle, } #endif +/** + * wma_is_pkt_drop_candidate() - check if the mgmt frame should be droppped + * @wma_handle: wma handle + * @peer_addr: peer MAC address + * @subtype: Management frame subtype + * + * This function is used to decide if a particular management frame should be + * dropped to prevent DOS attack. Timestamp is used to decide the DOS attack. + * + * Return: true if the packet should be dropped and false oterwise + */ +static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle, + uint8_t *peer_addr, uint8_t subtype) +{ + struct ol_txrx_peer_t *peer; + struct ol_txrx_pdev_t *pdev_ctx; + uint8_t peer_id; + bool should_drop = false; + + /* + * Currently this function handles only Disassoc, + * Deauth and Assoc req frames. Return false for + * all other frames. + */ + if (subtype != IEEE80211_FC0_SUBTYPE_DISASSOC && + subtype != IEEE80211_FC0_SUBTYPE_DEAUTH && + subtype != IEEE80211_FC0_SUBTYPE_ASSOC_REQ) { + should_drop = false; + goto end; + } + + pdev_ctx = cds_get_context(QDF_MODULE_ID_TXRX); + if (!pdev_ctx) { + WMA_LOGE(FL("Failed to get the context")); + should_drop = true; + goto end; + } + + peer = ol_txrx_find_peer_by_addr(pdev_ctx, peer_addr, &peer_id); + if (!peer) { + if (SIR_MAC_MGMT_ASSOC_REQ != subtype) { + WMA_LOGI( + FL("Received mgmt frame: %0x from unknow peer: %pM"), + subtype, peer_addr); + should_drop = true; + } + goto end; + } + + switch (subtype) { + case SIR_MAC_MGMT_ASSOC_REQ: + if (peer->last_assoc_rcvd) { + if (qdf_get_system_timestamp() - peer->last_assoc_rcvd < + WMA_MGMT_FRAME_DETECT_DOS_TIMER) { + WMA_LOGI(FL("Dropping Assoc Req received")); + should_drop = true; + } + } + peer->last_assoc_rcvd = qdf_get_system_timestamp(); + break; + case SIR_MAC_MGMT_DISASSOC: + if (peer->last_disassoc_rcvd) { + if (qdf_get_system_timestamp() - + peer->last_disassoc_rcvd < + WMA_MGMT_FRAME_DETECT_DOS_TIMER) { + WMA_LOGI(FL("Dropping DisAssoc received")); + should_drop = true; + } + } + peer->last_disassoc_rcvd = qdf_get_system_timestamp(); + break; + case SIR_MAC_MGMT_DEAUTH: + if (peer->last_deauth_rcvd) { + if (qdf_get_system_timestamp() - + peer->last_deauth_rcvd < + WMA_MGMT_FRAME_DETECT_DOS_TIMER) { + WMA_LOGI(FL("Dropping Deauth received")); + should_drop = true; + } + } + peer->last_deauth_rcvd = qdf_get_system_timestamp(); + break; + default: + break; + } + +end: + return should_drop; +} + /** * wma_mgmt_rx_process() - process management rx frame. * @handle: wma handle @@ -3028,6 +3118,12 @@ static int wma_mgmt_rx_process(void *handle, uint8_t *data, #endif /* WLAN_FEATURE_11W */ rx_pkt->pkt_meta.sessionId = (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id); + + if (wma_is_pkt_drop_candidate(wma_handle, wh->i_addr2, mgt_subtype)) { + cds_pkt_return_packet(rx_pkt); + return -EINVAL; + } + wma_handle->mgmt_rx(wma_handle, rx_pkt); return 0; }