qcacmn: Delete pmkid and single pmkid on connect failure

Add logic to delete the pmkid and single pmkid depending on
connect response status code and failure.

Change-Id: I7a27f887173ba7cdc13c3ce49ded5d2fcc8198fa
CRs-Fixed: 2792774
Tento commit je obsažen v:
gaurank kathpalia
2020-09-28 17:58:47 +05:30
odevzdal snandini
rodič 6ef375e0fb
revize 77f0dd0632
3 změnil soubory, kde provedl 115 přidání a 11 odebrání

Zobrazit soubor

@@ -401,6 +401,30 @@ void cm_calculate_scores(struct wlan_objmgr_pdev *pdev,
}
#endif
static inline void cm_delete_pmksa_for_bssid(struct cnx_mgr *cm_ctx,
struct qdf_mac_addr *bssid)
{
struct wlan_crypto_pmksa pmksa = {0};
qdf_copy_macaddr(&pmksa.bssid, bssid);
wlan_crypto_set_del_pmksa(cm_ctx->vdev, &pmksa, false);
}
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
static inline
void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx,
struct qdf_mac_addr *bssid)
{
cm_delete_pmksa_for_bssid(cm_ctx, bssid);
}
#else
static inline
void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx,
struct qdf_mac_addr *bssid)
{
}
#endif
static inline void
cm_set_pmf_caps(struct cm_connect_req *cm_req, struct scan_filter *filter)
{
@@ -708,27 +732,28 @@ static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx,
{
struct scan_cache_node *scan_node = NULL;
qdf_list_node_t *cur_node = NULL, *next_node = NULL;
struct scan_cache_node *cur_candidate;
struct scan_cache_node *new_candidate = NULL, *prev_candidate;
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
prev_candidate = cm_req->connect_req.cur_candidate;
if (cm_req->connect_req.connect_attempts >=
cm_ctx->max_connect_attempts) {
mlme_info(CM_PREFIX_FMT "%d attempts tried, max %d",
CM_PREFIX_REF(vdev_id, cm_req->cm_id),
cm_req->connect_req.connect_attempts,
cm_ctx->max_connect_attempts);
return QDF_STATUS_E_FAILURE;
status = QDF_STATUS_E_FAILURE;
goto flush_single_pmk;
}
cur_candidate = cm_req->connect_req.cur_candidate;
/*
* Get next candidate if cur_candidate is not NULL, else get
* Get next candidate if prev_candidate is not NULL, else get
* the first candidate
*/
if (cur_candidate)
if (prev_candidate)
qdf_list_peek_next(cm_req->connect_req.candidate_list,
&cur_candidate->node, &cur_node);
&prev_candidate->node, &cur_node);
else
qdf_list_peek_front(cm_req->connect_req.candidate_list,
&cur_node);
@@ -740,7 +765,7 @@ static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx,
node);
status = cm_validate_candidate(cm_ctx, scan_node->entry);
if (QDF_IS_STATUS_SUCCESS(status)) {
cur_candidate = scan_node;
new_candidate = scan_node;
break;
}
@@ -756,13 +781,23 @@ static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx,
mlme_debug(CM_PREFIX_FMT "No more candidates left",
CM_PREFIX_REF(vdev_id, cm_req->cm_id));
cm_req->connect_req.cur_candidate = NULL;
return QDF_STATUS_E_FAILURE;
status = QDF_STATUS_E_FAILURE;
goto flush_single_pmk;
}
cm_req->connect_req.connect_attempts++;
cm_req->connect_req.cur_candidate = cur_candidate;
cm_req->connect_req.cur_candidate = new_candidate;
return QDF_STATUS_SUCCESS;
flush_single_pmk:
/*
* If connection fails with Single PMK bssid (prev candidate),
* clear the pmk entry.
*/
if (prev_candidate && util_scan_entry_single_pmk(prev_candidate->entry))
cm_delete_pmksa_for_single_pmk_bssid(cm_ctx,
&prev_candidate->entry->bssid);
return status;
}
static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
@@ -1115,6 +1150,13 @@ QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
}
if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) {
/*
* On successful connection to sae single pmk AP,
* clear all the single pmk AP.
*/
if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id))
wlan_crypto_selective_clear_sae_single_pmk_entries(vdev,
&resp->bssid);
qdf_status =
cm_sm_deliver_event(vdev,
WLAN_CM_SM_EV_CONNECT_SUCCESS,
@@ -1128,6 +1170,15 @@ QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
goto post_err;
}
/*
* Delete the PMKID of the BSSID for which the assoc reject is
* received from the AP due to invalid PMKID reason.
* This will avoid the driver trying to connect to same AP with
* the same stale PMKID. when connection is tried again with this AP.
*/
if (resp->reason_code == STATUS_INVALID_PMKID)
cm_delete_pmksa_for_bssid(cm_ctx, &resp->bssid);
/* In case of failure try with next candidate */
qdf_status =
cm_sm_deliver_event(vdev,
@@ -1136,7 +1187,12 @@ QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
if (QDF_IS_STATUS_SUCCESS(qdf_status))
return qdf_status;
/*
* If connection fails with Single PMK bssid, clear this pmk
* entry in case of post failure.
*/
if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id))
cm_delete_pmksa_for_single_pmk_bssid(cm_ctx, &resp->bssid);
post_err:
/*
* If there is a event posting error it means the SM state is not in

Zobrazit soubor

@@ -504,6 +504,18 @@ cm_fill_bss_info_in_connect_rsp_by_cm_id(struct cnx_mgr *cm_ctx,
wlan_cm_id cm_id,
struct wlan_cm_connect_rsp *resp);
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
bool cm_is_cm_id_current_candidate_single_pmk(struct cnx_mgr *cm_ctx,
wlan_cm_id cm_id);
#else
static inline
bool cm_is_cm_id_current_candidate_single_pmk(struct cnx_mgr *cm_ctx,
wlan_cm_id cm_id)
{
return false;
}
#endif
/**
* cm_flush_pending_request() - Flush all pending requests matching flush prefix
* @cm_ctx: connection manager context

Zobrazit soubor

@@ -402,6 +402,42 @@ cm_fill_bss_info_in_connect_rsp_by_cm_id(struct cnx_mgr *cm_ctx,
return QDF_STATUS_E_FAILURE;
}
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
bool cm_is_cm_id_current_candidate_single_pmk(struct cnx_mgr *cm_ctx,
wlan_cm_id cm_id)
{
qdf_list_node_t *cur_node = NULL, *next_node = NULL;
struct cm_req *cm_req;
uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
struct scan_cache_node *candidate;
bool is_single_pmk = false;
if (prefix != CONNECT_REQ_PREFIX)
return is_single_pmk;
cm_req_lock_acquire(cm_ctx);
qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
while (cur_node) {
qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
cm_req = qdf_container_of(cur_node, struct cm_req, node);
if (cm_req->cm_id == cm_id) {
candidate = cm_req->connect_req.cur_candidate;
if (candidate &&
util_scan_entry_single_pmk(candidate->entry))
is_single_pmk = true;
break;
}
cur_node = next_node;
next_node = NULL;
}
cm_req_lock_release(cm_ctx);
return is_single_pmk;
}
#endif
QDF_STATUS cm_add_req_to_list_and_indicate_osif(struct cnx_mgr *cm_ctx,
struct cm_req *cm_req,
enum wlan_cm_source source)