瀏覽代碼

qcacld-3.0: Send update OWE info event

When receiving assoc request from OWE STA, always send update OWE
info event which contains the following information:
- MAC address of STA
- RSN IE in assoc request
- DH IE in assoc request

Change-Id: I7017c5d2730e493db2472ae53d5dfa69553cfe45
CRs-Fixed: 2396925
Min Liu 6 年之前
父節點
當前提交
e34708a91d

+ 25 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -3640,4 +3640,29 @@ QDF_STATUS hdd_md_host_evt_cb(void *ctx, struct sir_md_evt *event);
  */
 void hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle, uint8_t vdev_id);
 
+/**
+ * hdd_send_update_owe_info_event - Send update OWE info event
+ * @adapter: Pointer to adapter
+ * @sta_addr: MAC address of peer STA
+ * @owe_ie: OWE IE
+ * @owe_ie_len: Length of OWE IE
+ *
+ * Send update OWE info event to hostapd
+ *
+ * Return: none
+ */
+#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
+void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
+				    uint8_t sta_addr[],
+				    uint8_t *owe_ie,
+				    uint32_t owe_ie_len);
+#else
+static inline void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
+						  uint8_t sta_addr[],
+						  uint8_t *owe_ie,
+						  uint32_t owe_ie_len)
+{
+}
+#endif
+
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 21 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -20999,6 +20999,27 @@ void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
 }
 #endif
 
+#ifdef CFG80211_EXTERNAL_DH_UPDATE_SUPPORT
+void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
+				    uint8_t sta_addr[],
+				    uint8_t *owe_ie,
+				    uint32_t owe_ie_len)
+{
+	struct cfg80211_update_owe_info owe_info;
+	struct net_device *dev = adapter->dev;
+
+	hdd_enter_dev(dev);
+
+	qdf_mem_copy(owe_info.bssid, sta_addr, ETH_ALEN);
+	owe_info.ie = owe_ie;
+	owe_info.ie_len = owe_ie_len;
+
+	cfg80211_update_owe_info_event(dev, &owe_info, GFP_KERNEL);
+
+	hdd_exit();
+}
+#endif
+
 /**
  * struct cfg80211_ops - cfg80211_ops
  *

+ 10 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -2440,6 +2440,16 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 		hdd_debug("%s", maxAssocExceededEvent);
 		break;
 	case eSAP_STA_ASSOC_IND:
+		if (pSapEvent->sapevt.sapAssocIndication.owe_ie) {
+			hdd_send_update_owe_info_event(adapter,
+			      pSapEvent->sapevt.sapAssocIndication.staMac.bytes,
+			      pSapEvent->sapevt.sapAssocIndication.owe_ie,
+			      pSapEvent->sapevt.sapAssocIndication.owe_ie_len);
+			qdf_mem_free(
+				   pSapEvent->sapevt.sapAssocIndication.owe_ie);
+			pSapEvent->sapevt.sapAssocIndication.owe_ie = NULL;
+			pSapEvent->sapevt.sapAssocIndication.owe_ie_len = 0;
+		}
 		return QDF_STATUS_SUCCESS;
 
 	case eSAP_DISCONNECT_ALL_P2P_CLIENT:

+ 10 - 0
core/mac/inc/sir_api.h

@@ -1120,6 +1120,16 @@ struct assoc_ind {
 	bool is_sae_authenticated;
 };
 
+/**
+ * struct owe_assoc_ind - owe association indication
+ * @node : List entry element
+ * @assoc_ind: pointer to assoc ind
+ */
+struct owe_assoc_ind {
+	qdf_list_node_t node;
+	struct assoc_ind *assoc_ind;
+};
+
 /* / Definition for Association confirm */
 /* / ---> MAC */
 struct assoc_cnf {

+ 2 - 0
core/sap/inc/sap_api.h

@@ -255,6 +255,8 @@ typedef struct sap_StationAssocIndication_s {
 	eCsrEncryptionType negotiatedMCEncryptionType;
 	bool fAuthRequired;
 	uint8_t ecsa_capable;
+	uint32_t owe_ie_len;
+	uint8_t *owe_ie;
 } tSap_StationAssocIndication;
 
 typedef struct sap_StationAssocReassocCompleteEvent_s {

+ 118 - 0
core/sap/src/sap_fsm.c

@@ -1342,6 +1342,101 @@ static void sap_handle_acs_scan_event(struct sap_context *sap_context,
 }
 #endif
 
+#define DH_OUI_TYPE      "\x20"
+#define DH_OUI_TYPE_SIZE (1)
+/**
+ * sap_fill_owe_ie_in_assoc_ind() - Fill OWE IE in assoc indication
+ * Function to fill OWE IE in assoc indication
+ * @assoc_ind: SAP STA association indication
+ * @sme_assoc_ind: SME association indication
+ *
+ * This function is to get OWE IEs (RSN IE, DH IE etc) from assoc request
+ * and fill them in association indication.
+ *
+ * Return: true for success and false for failure
+ */
+static bool sap_fill_owe_ie_in_assoc_ind(tSap_StationAssocIndication *assoc_ind,
+					 struct assoc_ind *sme_assoc_ind)
+{
+	uint32_t owe_ie_len, rsn_ie_len, dh_ie_len;
+	const uint8_t *rsn_ie, *dh_ie;
+
+	rsn_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_RSN,
+					  assoc_ind->assocReqPtr,
+					  assoc_ind->assocReqLength);
+	if (!rsn_ie) {
+		QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "RSN IE is not present");
+		return false;
+	}
+	rsn_ie_len = rsn_ie[1] + 2;
+	if (rsn_ie_len < DOT11F_IE_RSN_MIN_LEN ||
+	    rsn_ie_len > DOT11F_IE_RSN_MAX_LEN) {
+		QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid RSN IE len %d",
+				rsn_ie_len);
+		return false;
+	}
+
+	dh_ie = wlan_get_ext_ie_ptr_from_ext_id(DH_OUI_TYPE, DH_OUI_TYPE_SIZE,
+					   assoc_ind->assocReqPtr,
+					   (uint16_t)assoc_ind->assocReqLength);
+	if (!dh_ie) {
+		QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "DH IE is not present");
+		return false;
+	}
+	dh_ie_len = dh_ie[1] + 2;
+	if (dh_ie_len < DOT11F_IE_DH_PARAMETER_ELEMENT_MIN_LEN ||
+	    dh_ie_len > DOT11F_IE_DH_PARAMETER_ELEMENT_MAX_LEN) {
+		QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid DH IE len %d",
+				dh_ie_len);
+		return false;
+	}
+
+	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
+		  FL("rsn_ie_len = %d, dh_ie_len = %d"), rsn_ie_len, dh_ie_len);
+
+	owe_ie_len = rsn_ie_len + dh_ie_len;
+	assoc_ind->owe_ie = qdf_mem_malloc(owe_ie_len);
+	if (!assoc_ind->owe_ie)
+		return false;
+
+	qdf_mem_copy(assoc_ind->owe_ie, rsn_ie, rsn_ie_len);
+	qdf_mem_copy(assoc_ind->owe_ie + rsn_ie_len, dh_ie, dh_ie_len);
+	assoc_ind->owe_ie_len = owe_ie_len;
+
+	return true;
+}
+
+/**
+ * sap_save_owe_pending_assoc_ind() - Save pending assoc indication
+ * Function to save pending assoc indication in SAP context
+ * @sap_ctx: SAP context
+ * @sme_assoc_ind: SME association indication
+ *
+ * This function is to save pending assoc indication in linked list
+ * in SAP context.
+ *
+ * Return: true for success and false for failure
+ */
+static bool sap_save_owe_pending_assoc_ind(struct sap_context *sap_ctx,
+				       struct assoc_ind *sme_assoc_ind)
+{
+	struct owe_assoc_ind *assoc_ind;
+	QDF_STATUS status;
+
+	assoc_ind = qdf_mem_malloc(sizeof(*assoc_ind));
+	if (!assoc_ind)
+		return false;
+	assoc_ind->assoc_ind = sme_assoc_ind;
+	status = qdf_list_insert_back(&sap_ctx->owe_pending_assoc_ind_list,
+				      &assoc_ind->node);
+	if (QDF_STATUS_SUCCESS != status) {
+		qdf_mem_free(assoc_ind);
+		return false;
+	}
+
+	return true;
+}
+
 /**
  * sap_signal_hdd_event() - send event notification
  * @sap_ctx: Sap Context
@@ -1414,6 +1509,29 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx,
 			    csr_roaminfo->u.pConnectedProfile->mcEncryptionType;
 			assoc_ind->fAuthRequired = csr_roaminfo->fAuthRequired;
 		}
+		if (csr_roaminfo->owe_pending_assoc_ind) {
+			if (!sap_fill_owe_ie_in_assoc_ind(assoc_ind,
+					 csr_roaminfo->owe_pending_assoc_ind)) {
+				QDF_TRACE(QDF_MODULE_ID_SAP,
+					  QDF_TRACE_LEVEL_ERROR,
+					  FL("Failed to fill OWE IE"));
+				qdf_mem_free(csr_roaminfo->
+					     owe_pending_assoc_ind);
+				csr_roaminfo->owe_pending_assoc_ind = NULL;
+				return QDF_STATUS_E_INVAL;
+			}
+			if (!sap_save_owe_pending_assoc_ind(sap_ctx,
+					 csr_roaminfo->owe_pending_assoc_ind)) {
+				QDF_TRACE(QDF_MODULE_ID_SAP,
+					  QDF_TRACE_LEVEL_ERROR,
+					  FL("Failed to save assoc ind"));
+				qdf_mem_free(csr_roaminfo->
+					     owe_pending_assoc_ind);
+				csr_roaminfo->owe_pending_assoc_ind = NULL;
+				return QDF_STATUS_E_INVAL;
+			}
+			csr_roaminfo->owe_pending_assoc_ind = NULL;
+		}
 		break;
 	case eSAP_START_BSS_EVENT:
 		sap_ap_event.sapHddEventCode = eSAP_START_BSS_EVENT;

+ 1 - 0
core/sap/src/sap_internal.h

@@ -226,6 +226,7 @@ struct sap_context {
 	uint8_t sap_sta_id;
 	bool dfs_cac_offload;
 	bool is_chan_change_inprogress;
+	qdf_list_t owe_pending_assoc_ind_list;
 };
 
 /*----------------------------------------------------------------------------

+ 73 - 0
core/sap/src/sap_module.c

@@ -242,6 +242,67 @@ struct sap_context *sap_create_ctx(void)
 	return sap_ctx;
 } /* sap_create_ctx */
 
+static QDF_STATUS wlansap_owe_init(struct sap_context *sap_ctx)
+{
+	qdf_list_create(&sap_ctx->owe_pending_assoc_ind_list, 0);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static void wlansap_owe_cleanup(struct sap_context *sap_ctx)
+{
+	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 (!sap_ctx) {
+		QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid SAP context");
+		return;
+	}
+
+	mac = sap_get_mac_context();
+	if (!mac) {
+		QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid MAC context");
+		return;
+	}
+
+	if (QDF_STATUS_SUCCESS !=
+	    qdf_list_peek_front(&sap_ctx->owe_pending_assoc_ind_list,
+				&node)) {
+		QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
+				"Failed to find assoc ind list");
+		return;
+	}
+
+	while (node) {
+		qdf_list_peek_next(&sap_ctx->owe_pending_assoc_ind_list,
+				   node, &next_node);
+		owe_assoc_ind = qdf_container_of(node, struct owe_assoc_ind,
+						 node);
+		status = qdf_list_remove_node(
+					   &sap_ctx->owe_pending_assoc_ind_list,
+					   node);
+		if (status == QDF_STATUS_SUCCESS) {
+			assoc_ind = owe_assoc_ind->assoc_ind;
+			qdf_mem_free(owe_assoc_ind);
+			/* TODO: disassoc OWE STA */
+			qdf_mem_free(assoc_ind);
+		} else {
+			QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
+					"Failed to remove assoc ind");
+		}
+		node = next_node;
+		next_node = NULL;
+	}
+}
+
+static void wlansap_owe_deinit(struct sap_context *sap_ctx)
+{
+	qdf_list_destroy(&sap_ctx->owe_pending_assoc_ind_list);
+}
+
 QDF_STATUS sap_init_ctx(struct sap_context *sap_ctx,
 			 enum QDF_OPMODE mode,
 			 uint8_t *addr, uint32_t session_id, bool reinit)
@@ -294,6 +355,15 @@ QDF_STATUS sap_init_ctx(struct sap_context *sap_ctx,
 			ucfg_scan_register_requester(mac->psoc, "SAP",
 					sap_scan_event_callback, sap_ctx);
 
+	if (!reinit) {
+		status = wlansap_owe_init(sap_ctx);
+		if (QDF_STATUS_SUCCESS != status) {
+			QDF_TRACE_ERROR(QDF_MODULE_ID_SAP,
+					"OWE init failed");
+			return QDF_STATUS_E_FAILURE;
+		}
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -311,6 +381,9 @@ QDF_STATUS sap_deinit_ctx(struct sap_context *sap_ctx)
 		return QDF_STATUS_E_FAULT;
 	}
 
+	wlansap_owe_cleanup(sap_ctx);
+	wlansap_owe_deinit(sap_ctx);
+
 	mac = sap_get_mac_context();
 	if (!mac) {
 		QDF_TRACE_ERROR(QDF_MODULE_ID_SAP, "Invalid MAC context");

+ 1 - 0
core/sme/inc/csr_api.h

@@ -1181,6 +1181,7 @@ struct csr_roam_info {
 #ifdef WLAN_FEATURE_SAE
 	struct sir_sae_info *sae_info;
 #endif
+	struct assoc_ind *owe_pending_assoc_ind;
 };
 
 typedef struct sSirSmeAssocIndToUpperLayerCnf {

+ 21 - 12
core/sme/src/csr/csr_api_roam.c

@@ -10804,6 +10804,13 @@ csr_roam_chk_lnk_assoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
 		} else {
 			roam_info->fAuthRequired = true;
 		}
+		if (csr_akm_type == eCSR_AUTH_TYPE_OWE) {
+			roam_info->owe_pending_assoc_ind = qdf_mem_malloc(
+							    sizeof(*pAssocInd));
+			if (roam_info->owe_pending_assoc_ind)
+				qdf_mem_copy(roam_info->owe_pending_assoc_ind,
+					     pAssocInd, sizeof(*pAssocInd));
+		}
 		status = csr_roam_call_callback(mac_ctx, sessionId,
 					roam_info, 0, eCSR_ROAM_INFRA_IND,
 					eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND);
@@ -10833,18 +10840,20 @@ csr_roam_chk_lnk_assoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
 		}
 	}
 
-	/* Send Association completion message to PE */
-	status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status,
-					mac_status_code);
-	/*
-	 * send a message to CSR itself just to avoid the EAPOL frames going
-	 * OTA before association response
-	 */
-	if (CSR_IS_INFRA_AP(roam_info->u.pConnectedProfile) &&
-	    roam_info->statusCode != eSIR_SME_ASSOC_REFUSED) {
-		roam_info->fReassocReq = pAssocInd->reassocReq;
-		status = csr_send_assoc_ind_to_upper_layer_cnf_msg(mac_ctx,
-						pAssocInd, status, sessionId);
+	if (csr_akm_type != eCSR_AUTH_TYPE_OWE) {
+		/* Send Association completion message to PE */
+		status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status,
+						mac_status_code);
+		/*
+		 * send a message to CSR itself just to avoid the EAPOL frames
+		 * going OTA before association response
+		 */
+		if (CSR_IS_INFRA_AP(roam_info->u.pConnectedProfile) &&
+		    roam_info->statusCode != eSIR_SME_ASSOC_REFUSED) {
+			roam_info->fReassocReq = pAssocInd->reassocReq;
+			status = csr_send_assoc_ind_to_upper_layer_cnf_msg(
+					mac_ctx, pAssocInd, status, sessionId);
+		}
 	}
 
 	qdf_mem_free(roam_info);