summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/dp/txrx/ol_rx_defrag.c34
-rw-r--r--core/dp/txrx/ol_rx_pn.c37
-rw-r--r--core/dp/txrx/ol_rx_pn.h14
-rw-r--r--core/dp/txrx/ol_txrx.c18
-rw-r--r--core/dp/txrx/ol_txrx_types.h4
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c12
6 files changed, 96 insertions, 23 deletions
diff --git a/core/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c
index a58047242ed4..9ba9fc67e8a5 100644
--- a/core/dp/txrx/ol_rx_defrag.c
+++ b/core/dp/txrx/ol_rx_defrag.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -443,6 +443,8 @@ ol_rx_reorder_store_frag(ol_txrx_pdev_handle pdev,
struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem;
uint16_t frxseq, rxseq, seq;
htt_pdev_handle htt_pdev = pdev->htt_pdev;
+ void *rx_desc;
+ uint8_t index;
seq = seq_num & peer->tids_rx_reorder[tid].win_sz_mask;
qdf_assert(seq == 0);
@@ -456,6 +458,28 @@ ol_rx_reorder_store_frag(ol_txrx_pdev_handle pdev,
IEEE80211_SEQ_FRAG_MASK;
more_frag = mac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
+ rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag);
+ qdf_assert(htt_rx_msdu_has_wlan_mcast_flag(htt_pdev, rx_desc));
+ index = htt_rx_msdu_is_wlan_mcast(htt_pdev, rx_desc) ?
+ txrx_sec_mcast : txrx_sec_ucast;
+
+ /*
+ * Multicast/Broadcast frames should not be fragmented so drop
+ * such frames.
+ */
+ if (index != txrx_sec_ucast) {
+ ol_rx_frames_free(htt_pdev, frag);
+ return;
+ }
+
+ if (peer->security[index].sec_type != htt_sec_type_none &&
+ !htt_rx_mpdu_is_encrypted(htt_pdev, rx_desc)) {
+ ol_txrx_err("Unencrypted fragment received in security mode %d",
+ peer->security[index].sec_type);
+ ol_rx_frames_free(htt_pdev, frag);
+ return;
+ }
+
if ((!more_frag) && (!fragno) && (!rx_reorder_array_elem->head)) {
ol_rx_fraglist_insert(htt_pdev, &rx_reorder_array_elem->head,
&rx_reorder_array_elem->tail, frag, &all_frag_present);
@@ -697,7 +721,13 @@ ol_rx_defrag(ol_txrx_pdev_handle pdev,
while (cur) {
tmp_next = qdf_nbuf_next(cur);
qdf_nbuf_set_next(cur, NULL);
- if (!ol_rx_pn_check_base(vdev, peer, tid, cur)) {
+ /*
+ * Strict PN check between the first fragment of the current
+ * frame and the last fragment of the previous frame is not
+ * necessary.
+ */
+ if (!ol_rx_pn_check_base(vdev, peer, tid, cur,
+ (cur == frag_list) ? false : true)) {
/* PN check failed,discard frags */
if (prev) {
qdf_nbuf_set_next(prev, NULL);
diff --git a/core/dp/txrx/ol_rx_pn.c b/core/dp/txrx/ol_rx_pn.c
index dd09c3f50c71..0bd8e75e5191 100644
--- a/core/dp/txrx/ol_rx_pn.c
+++ b/core/dp/txrx/ol_rx_pn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2013-2017, 2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -37,25 +37,36 @@
} while (0)
int ol_rx_pn_cmp24(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode)
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk)
{
- int rc = ((new_pn->pn24 & 0xffffff) <= (old_pn->pn24 & 0xffffff));
- return rc;
+ if (strict_chk)
+ return ((new_pn->pn24 & 0xffffff) - (old_pn->pn24 & 0xffffff)
+ != 1);
+ else
+ return ((new_pn->pn24 & 0xffffff) <= (old_pn->pn24 & 0xffffff));
}
int ol_rx_pn_cmp48(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode)
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk)
{
- int rc = ((new_pn->pn48 & 0xffffffffffffULL) <=
- (old_pn->pn48 & 0xffffffffffffULL));
- return rc;
+ if (strict_chk)
+ return ((new_pn->pn48 & 0xffffffffffffULL) -
+ (old_pn->pn48 & 0xffffffffffffULL) != 1);
+ else
+ return ((new_pn->pn48 & 0xffffffffffffULL) <=
+ (old_pn->pn48 & 0xffffffffffffULL));
}
int ol_rx_pn_wapi_cmp(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode)
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk)
{
int pn_is_replay = 0;
+ /* TODO Strick check for WAPI is not implemented*/
+
if (new_pn->pn128[1] == old_pn->pn128[1])
pn_is_replay = (new_pn->pn128[0] <= old_pn->pn128[0]);
else
@@ -73,7 +84,7 @@ int ol_rx_pn_wapi_cmp(union htt_rx_pn_t *new_pn,
qdf_nbuf_t
ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev,
struct ol_txrx_peer_t *peer,
- unsigned int tid, qdf_nbuf_t msdu_list)
+ unsigned int tid, qdf_nbuf_t msdu_list, bool strict_chk)
{
struct ol_txrx_pdev_t *pdev = vdev->pdev;
union htt_rx_pn_t *last_pn;
@@ -132,7 +143,7 @@ ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev,
pn_is_replay =
pdev->rx_pn[peer->security[index].sec_type].
cmp(&new_pn, last_pn, index == txrx_sec_ucast,
- vdev->opmode);
+ vdev->opmode, strict_chk);
} else {
last_pn_valid = peer->tids_last_pn_valid[tid] = 1;
}
@@ -253,7 +264,7 @@ ol_rx_pn_check(struct ol_txrx_vdev_t *vdev,
struct ol_txrx_peer_t *peer, unsigned int tid,
qdf_nbuf_t msdu_list)
{
- msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list);
+ msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list, false);
ol_rx_fwd_check(vdev, peer, tid, msdu_list);
}
@@ -262,7 +273,7 @@ ol_rx_pn_check_only(struct ol_txrx_vdev_t *vdev,
struct ol_txrx_peer_t *peer,
unsigned int tid, qdf_nbuf_t msdu_list)
{
- msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list);
+ msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list, false);
ol_rx_deliver(vdev, peer, tid, msdu_list);
}
diff --git a/core/dp/txrx/ol_rx_pn.h b/core/dp/txrx/ol_rx_pn.h
index 8e0c007b091d..fa64c3e5133c 100644
--- a/core/dp/txrx/ol_rx_pn.h
+++ b/core/dp/txrx/ol_rx_pn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2014-2017, 2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -24,13 +24,16 @@
#include <ol_txrx_api.h> /* ol_txrx_peer_t, etc. */
int ol_rx_pn_cmp24(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode);
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk);
int ol_rx_pn_cmp48(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode);
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk);
int ol_rx_pn_wapi_cmp(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode);
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk);
/**
* @brief If applicable, check the Packet Number to detect replays.
@@ -87,11 +90,12 @@ ol_rx_pn_check_only(struct ol_txrx_vdev_t *vdev,
* @param tid - which TID within the peer the rx frames belong to
* @param msdu_list - NULL-terminated list of MSDUs to perform PN check on
* (if PN check is applicable, i.e. PN length > 0)
+ * @param strick_chk - if PN consecutive stric check is needed or not
* @return list of netbufs that didn't fail the PN check
*/
qdf_nbuf_t
ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev,
struct ol_txrx_peer_t *peer,
- unsigned int tid, qdf_nbuf_t msdu_list);
+ unsigned int tid, qdf_nbuf_t msdu_list, bool strict_chk);
#endif /* _OL_RX_PN_H_ */
diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c
index a180d80db35e..4b5bcadecd65 100644
--- a/core/dp/txrx/ol_txrx.c
+++ b/core/dp/txrx/ol_txrx.c
@@ -1949,14 +1949,32 @@ ol_txrx_pdev_post_attach(ol_txrx_pdev_handle pdev)
*/
qdf_mem_set(&pdev->rx_pn[0], sizeof(pdev->rx_pn), 0);
+ /* WEP: 24-bit PN */
+ pdev->rx_pn[htt_sec_type_wep40].len =
+ pdev->rx_pn[htt_sec_type_wep104].len =
+ pdev->rx_pn[htt_sec_type_wep128].len = 24;
+
+ pdev->rx_pn[htt_sec_type_wep40].cmp =
+ pdev->rx_pn[htt_sec_type_wep104].cmp =
+ pdev->rx_pn[htt_sec_type_wep128].cmp = ol_rx_pn_cmp24;
+
/* TKIP: 48-bit TSC, CCMP: 48-bit PN */
pdev->rx_pn[htt_sec_type_tkip].len =
pdev->rx_pn[htt_sec_type_tkip_nomic].len =
pdev->rx_pn[htt_sec_type_aes_ccmp].len = 48;
+
+ pdev->rx_pn[htt_sec_type_aes_ccmp_256].len =
+ pdev->rx_pn[htt_sec_type_aes_gcmp].len =
+ pdev->rx_pn[htt_sec_type_aes_gcmp_256].len = 48;
+
pdev->rx_pn[htt_sec_type_tkip].cmp =
pdev->rx_pn[htt_sec_type_tkip_nomic].cmp =
pdev->rx_pn[htt_sec_type_aes_ccmp].cmp = ol_rx_pn_cmp48;
+ pdev->rx_pn[htt_sec_type_aes_ccmp_256].cmp =
+ pdev->rx_pn[htt_sec_type_aes_gcmp].cmp =
+ pdev->rx_pn[htt_sec_type_aes_gcmp_256].cmp = ol_rx_pn_cmp48;
+
/* WAPI: 128-bit PN */
pdev->rx_pn[htt_sec_type_wapi].len = 128;
pdev->rx_pn[htt_sec_type_wapi].cmp = ol_rx_pn_wapi_cmp;
diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h
index 189aa21c6eb3..96f49bbc16c3 100644
--- a/core/dp/txrx/ol_txrx_types.h
+++ b/core/dp/txrx/ol_txrx_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, 2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -778,7 +778,7 @@ struct ol_txrx_pdev_t {
struct {
int (*cmp)(union htt_rx_pn_t *new,
union htt_rx_pn_t *old,
- int is_unicast, int opmode);
+ int is_unicast, int opmode, bool strict_chk);
int len;
} rx_pn[htt_num_sec_types];
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index d91035fef36b..91bc62da5d49 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, 2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -15384,6 +15384,12 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
QDF_STATUS qdf_ret_status;
hdd_context_t *pHddCtx;
hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
+ ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+
+ if (!pdev) {
+ hdd_err("DP pdev is NULL");
+ return -EINVAL;
+ }
ENTER();
@@ -15547,6 +15553,10 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
setKey.keyDirection = eSIR_TX_RX;
qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
}
+
+ ol_txrx_peer_flush_frags(pdev, pAdapter->sessionId,
+ setKey.peerMac.bytes);
+
if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
/* if a key is already installed, block all subsequent ones */
if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {