qcacld-3.0: Handle OWE info update from hostapd

Handle OWE info update from hostapd in the following path:
HDD->SAP->SME->CSR

Change-Id: I7584fb5db036d1643bd7d56076d30a0c75008a98
CRs-Fixed: 2397009
This commit is contained in:
Min Liu 2019-02-01 17:50:44 +08:00 committed by nshrivas
parent e34708a91d
commit 0daa098737
11 changed files with 348 additions and 2 deletions

View File

@ -19663,6 +19663,78 @@ wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
}
#endif
#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
/**
* __wlan_hdd_cfg80211_update_owe_info() - update OWE info
* @wiphy: Pointer to wiphy
* @dev: Pointer to network device
* @owe_info: Pointer to OWE info
*
* Return: 0 for success, non-zero for failure
*/
static int
__wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_update_owe_info *owe_info)
{
struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
QDF_STATUS status;
int errno = 0;
hdd_enter_dev(dev);
errno = wlan_hdd_validate_context(hdd_ctx);
if (errno)
return errno;
if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
hdd_err("Command not allowed in FTM mode");
return -EINVAL;
}
if (wlan_hdd_validate_session_id(adapter->vdev_id)) {
hdd_err("invalid session id: %d", adapter->vdev_id);
return -EINVAL;
}
hdd_debug("owe_status %d", owe_info->status);
status = wlansap_update_owe_info(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
owe_info->bssid, owe_info->ie,
owe_info->ie_len, owe_info->status);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Failed to update OWE info");
errno = qdf_status_to_os_return(status);
}
hdd_exit();
return errno;
}
/**
* wlan_hdd_cfg80211_update_owe_info() - update OWE info
* @wiphy: Pointer to wiphy
* @dev: Pointer to network device
* @owe_info: Pointer to OWE info
*
* Return: 0 for success, non-zero for failure
*/
static int
wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_update_owe_info *owe_info)
{
int ret;
cds_ssr_protect(__func__);
ret = __wlan_hdd_cfg80211_update_owe_info(wiphy, dev, owe_info);
cds_ssr_unprotect(__func__);
return ret;
}
#endif
void wlan_hdd_cfg80211_update_replay_counter_cb(
void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
@ -21113,6 +21185,9 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
#if defined(KERNEL_SUPPORT_11R_CFG80211)
.update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
#endif
#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
.update_owe_info = wlan_hdd_cfg80211_update_owe_info,
#endif
#ifdef FEATURE_WLAN_TDLS
.tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
.tdls_oper = wlan_hdd_cfg80211_tdls_oper,

View File

@ -1118,6 +1118,9 @@ struct assoc_ind {
tDot11fIEVHTCaps VHTCaps;
tSirMacCapabilityInfo capability_info;
bool is_sae_authenticated;
const uint8_t *owe_ie;
uint32_t owe_ie_len;
uint16_t owe_status;
};
/**
@ -1140,6 +1143,8 @@ struct assoc_cnf {
struct qdf_mac_addr peer_macaddr;
uint16_t aid;
tSirMacStatusCodes mac_status_code;
uint8_t *owe_ie;
uint32_t owe_ie_len;
};
/* / Enum definition for Wireless medium status change codes */

View File

@ -260,6 +260,8 @@ typedef struct sLimMlmStaContext {
#ifdef WLAN_FEATURE_11AX
bool he_capable;
#endif
uint8_t *owe_ie;
uint32_t owe_ie_len;
} tLimMlmStaContext, *tpLimMlmStaContext;
/* Structure definition to hold deferred messages queue parameters */

View File

@ -3084,12 +3084,16 @@ void __lim_process_sme_assoc_cnf_new(struct mac_context *mac_ctx, uint32_t msg_t
*/
sta_ds->mlmStaContext.mlmState =
eLIM_MLM_LINK_ESTABLISHED_STATE;
sta_ds->mlmStaContext.owe_ie = assoc_cnf.owe_ie;
sta_ds->mlmStaContext.owe_ie_len = assoc_cnf.owe_ie_len;
pe_debug("sending Assoc Rsp frame to STA (assoc id=%d)",
sta_ds->assocId);
lim_send_assoc_rsp_mgmt_frame(mac_ctx, QDF_STATUS_SUCCESS,
sta_ds->assocId, sta_ds->staAddr,
sta_ds->mlmStaContext.subType, sta_ds,
session_entry);
sta_ds->mlmStaContext.owe_ie = NULL;
sta_ds->mlmStaContext.owe_ie_len = 0;
goto end;
} else {
uint8_t add_pre_auth_context = true;
@ -3134,6 +3138,7 @@ end:
qdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]);
session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
}
qdf_mem_free(assoc_cnf.owe_ie);
}
static void __lim_process_sme_addts_req(struct mac_context *mac, uint32_t *pMsgBuf)

View File

@ -1307,6 +1307,9 @@ lim_send_assoc_rsp_mgmt_frame(struct mac_context *mac_ctx,
bytes += sizeof(tSirMacMgmtHdr) + payload;
if (sta)
bytes += sta->mlmStaContext.owe_ie_len;
qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
(void **)&packet);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
@ -1352,6 +1355,12 @@ lim_send_assoc_rsp_mgmt_frame(struct mac_context *mac_ctx,
qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
&add_ie[0], addn_ie_len);
if (sta && sta->mlmStaContext.owe_ie_len)
qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload
+ addn_ie_len,
sta->mlmStaContext.owe_ie,
sta->mlmStaContext.owe_ie_len);
if ((BAND_5G ==
lim_get_rf_band(pe_session->currentOperChannel)) ||
(pe_session->pePersona == QDF_P2P_CLIENT_MODE) ||

View File

@ -1340,6 +1340,20 @@ void sap_dfs_set_current_channel(void *sap_ctx);
*/
void wlansap_cleanup_cac_timer(struct sap_context *sap_ctx);
/**
* wlansap_update_owe_info() - Update OWE info
* @sap_ctx: sap context
* @peer: peer mac
* @ie: IE from hostapd
* @ie_len: IE length
* @owe_status: status from hostapd
*
* Return: QDF_STATUS
*/
QDF_STATUS wlansap_update_owe_info(struct sap_context *sap_ctx,
uint8_t *peer, const uint8_t *ie,
uint32_t ie_len, uint16_t owe_status);
#ifdef __cplusplus
}
#endif

View File

@ -287,7 +287,10 @@ static void wlansap_owe_cleanup(struct sap_context *sap_ctx)
if (status == QDF_STATUS_SUCCESS) {
assoc_ind = owe_assoc_ind->assoc_ind;
qdf_mem_free(owe_assoc_ind);
/* TODO: disassoc OWE STA */
assoc_ind->owe_ie = NULL;
assoc_ind->owe_ie_len = 0;
assoc_ind->owe_status = eSIR_MAC_UNSPEC_FAILURE_STATUS;
status = sme_update_owe_info(mac, assoc_ind);
qdf_mem_free(assoc_ind);
} else {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
@ -2471,3 +2474,161 @@ void wlansap_cleanup_cac_timer(struct sap_context *sap_ctx)
FL("sapdfs, force cleanup running dfs cac timer"));
}
}
#define DH_OUI_TYPE (0x20)
/**
* wlansap_validate_owe_ie() - validate OWE IE
* @ie: IE buffer
* @remaining_ie_len: remaining IE length
*
* Return: validated IE length, negative for failure
*/
static int wlansap_validate_owe_ie(const uint8_t *ie, uint32_t remaining_ie_len)
{
uint8_t ie_id, ie_len, ie_ext_id = 0;
if (remaining_ie_len < 2) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "IE too short");
return -EINVAL;
}
ie_id = ie[0];
ie_len = ie[1];
/* IEs that we are expecting in OWE IEs
* - RSN IE
* - DH IE
*/
switch (ie_id) {
case DOT11F_EID_RSN:
if (ie_len < DOT11F_IE_RSN_MIN_LEN ||
ie_len > DOT11F_IE_RSN_MAX_LEN) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
"Invalid RSN IE len %d", ie_len);
return -EINVAL;
}
ie_len += 2;
break;
case DOT11F_EID_DH_PARAMETER_ELEMENT:
ie_ext_id = ie[2];
if (ie_ext_id != DH_OUI_TYPE) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
"Invalid DH IE ID %d", ie_ext_id);
return -EINVAL;
}
if (ie_len < DOT11F_IE_DH_PARAMETER_ELEMENT_MIN_LEN ||
ie_len > DOT11F_IE_DH_PARAMETER_ELEMENT_MAX_LEN) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
"Invalid DH IE len %d", ie_len);
return -EINVAL;
}
ie_len += 2;
break;
default:
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid IE %d", ie_id);
return -EINVAL;
}
if (ie_len > remaining_ie_len) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid IE len");
return -EINVAL;
}
return ie_len;
}
/**
* wlansap_validate_owe_ies() - validate OWE IEs
* @ie: IE buffer
* @ie_len: IE length
*
* Return: true if validated
*/
static bool wlansap_validate_owe_ies(const uint8_t *ie, uint32_t ie_len)
{
const uint8_t *remaining_ie = ie;
uint32_t remaining_ie_len = ie_len;
int validated_len;
bool validated = true;
while (remaining_ie_len) {
validated_len = wlansap_validate_owe_ie(remaining_ie,
remaining_ie_len);
if (validated_len < 0) {
validated = false;
break;
}
remaining_ie += validated_len;
remaining_ie_len -= validated_len;
}
return validated;
}
QDF_STATUS wlansap_update_owe_info(struct sap_context *sap_ctx,
uint8_t *peer, const uint8_t *ie,
uint32_t ie_len, uint16_t owe_status)
{
struct mac_context *mac;
struct owe_assoc_ind *owe_assoc_ind;
struct assoc_ind *assoc_ind = NULL;
qdf_list_node_t *node = NULL, *next_node = NULL;
QDF_STATUS status;
if (!wlansap_validate_owe_ies(ie, ie_len)) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid OWE IE");
return QDF_STATUS_E_FAULT;
}
if (!sap_ctx) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid SAP context");
return QDF_STATUS_E_FAULT;
}
mac = sap_get_mac_context();
if (!mac) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid MAC context");
return QDF_STATUS_E_FAULT;
}
if (QDF_STATUS_SUCCESS !=
qdf_list_peek_front(&sap_ctx->owe_pending_assoc_ind_list,
&next_node)) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
"Failed to find assoc ind list");
return QDF_STATUS_E_FAILURE;
}
do {
node = next_node;
owe_assoc_ind = qdf_container_of(node, struct owe_assoc_ind,
node);
if (qdf_mem_cmp(peer,
owe_assoc_ind->assoc_ind->peerMacAddr,
QDF_MAC_ADDR_SIZE) == 0) {
status = qdf_list_remove_node(
&sap_ctx->owe_pending_assoc_ind_list,
node);
if (status != QDF_STATUS_SUCCESS) {
QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
"Failed to remove assoc ind");
return status;
}
assoc_ind = owe_assoc_ind->assoc_ind;
qdf_mem_free(owe_assoc_ind);
break;
}
} while (QDF_STATUS_SUCCESS ==
qdf_list_peek_next(&sap_ctx->owe_pending_assoc_ind_list,
node, &next_node));
if (assoc_ind) {
assoc_ind->owe_ie = ie;
assoc_ind->owe_ie_len = ie_len;
assoc_ind->owe_status = owe_status;
status = sme_update_owe_info(mac, assoc_ind);
qdf_mem_free(assoc_ind);
}
return status;
}

View File

@ -1466,4 +1466,14 @@ csr_get_channel_status(struct mac_context *mac, uint32_t channel_id);
* Return: none
*/
void csr_clear_channel_status(struct mac_context *mac);
/**
* csr_update_owe_info() - Update OWE info
* @mac: mac context
* @assoc_ind: assoc ind
*
* Return: QDF_STATUS
*/
QDF_STATUS csr_update_owe_info(struct mac_context *mac,
struct assoc_ind *assoc_ind);
#endif

View File

@ -3260,4 +3260,13 @@ QDF_STATUS sme_set_thermal_mgmt(mac_handle_t mac_handle,
QDF_STATUS sme_update_hidden_ssid_status_cb(mac_handle_t mac_handle,
hidden_ssid_cb cb);
/**
* sme_update_owe_info() - Update OWE info
* @mac: mac context
* @assoc_ind: assoc ind
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_update_owe_info(struct mac_context *mac,
struct assoc_ind *assoc_ind);
#endif /* #if !defined( __SME_API_H ) */

View File

@ -15022,3 +15022,17 @@ QDF_STATUS sme_update_hidden_ssid_status_cb(mac_handle_t mac_handle,
return status;
}
QDF_STATUS sme_update_owe_info(struct mac_context *mac,
struct assoc_ind *assoc_ind)
{
QDF_STATUS status;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_update_owe_info(mac, assoc_ind);
sme_release_global_lock(&mac->sme);
}
return status;
}

View File

@ -15748,7 +15748,8 @@ QDF_STATUS csr_send_assoc_cnf_msg(struct mac_context *mac,
struct assoc_cnf *pMsg;
struct scheduler_msg msg = { 0 };
sme_debug("Posting eWNI_SME_ASSOC_CNF to LIM.HalStatus: %d", Halstatus);
sme_debug("HalStatus: %d, mac_status_code %d",
Halstatus, mac_status_code);
do {
pMsg = qdf_mem_malloc(sizeof(*pMsg));
if (!pMsg)
@ -15769,6 +15770,15 @@ QDF_STATUS csr_send_assoc_cnf_msg(struct mac_context *mac,
QDF_MAC_ADDR_SIZE);
/* aid */
pMsg->aid = pAssocInd->aid;
/* OWE IE */
if (pAssocInd->owe_ie_len) {
pMsg->owe_ie = qdf_mem_malloc(pAssocInd->owe_ie_len);
if (!pMsg->owe_ie)
return QDF_STATUS_E_NOMEM;
qdf_mem_copy(pMsg->owe_ie, pAssocInd->owe_ie,
pAssocInd->owe_ie_len);
pMsg->owe_ie_len = pAssocInd->owe_ie_len;
}
msg.type = pMsg->messageType;
msg.bodyval = 0;
@ -21295,3 +21305,35 @@ QDF_STATUS csr_roam_synch_callback(struct mac_context *mac_ctx,
return status;
}
#endif
QDF_STATUS csr_update_owe_info(struct mac_context *mac,
struct assoc_ind *assoc_ind)
{
uint32_t session_id = CSR_SESSION_ID_INVALID;
QDF_STATUS status;
status = csr_roam_get_session_id_from_bssid(mac,
(struct qdf_mac_addr *)assoc_ind->bssId,
&session_id);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_debug("Couldn't find session_id for given BSSID");
return QDF_STATUS_E_FAILURE;
}
/* Send Association completion message to PE */
if (assoc_ind->owe_status)
status = QDF_STATUS_E_INVAL;
status = csr_send_assoc_cnf_msg(mac, assoc_ind, status,
assoc_ind->owe_status);
/*
* send a message to CSR itself just to avoid the EAPOL frames
* going OTA before association response
*/
if (assoc_ind->owe_status == 0)
status = csr_send_assoc_ind_to_upper_layer_cnf_msg(mac,
assoc_ind,
status,
session_id);
return status;
}