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:
parent
e34708a91d
commit
0daa098737
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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) ||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 ) */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user