|
@@ -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;
|
|
|
+}
|