diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 5a6fb85187..480ecc6472 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -20230,17 +20230,11 @@ fn_end: } #if defined(USE_CFG80211_DEL_STA_V2) -/** - * wlan_hdd_del_station() - delete station wrapper - * @adapter: pointer to the hdd adapter - * - * Return: Errno - */ -int wlan_hdd_del_station(struct hdd_adapter *adapter) +int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac) { struct station_del_parameters del_sta; - del_sta.mac = NULL; + del_sta.mac = mac; del_sta.subtype = IEEE80211_STYPE_DEAUTH >> 4; del_sta.reason_code = WLAN_REASON_DEAUTH_LEAVING; @@ -20248,10 +20242,10 @@ int wlan_hdd_del_station(struct hdd_adapter *adapter) adapter->dev, &del_sta); } #else -int wlan_hdd_del_station(struct hdd_adapter *adapter) +int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac) { return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, - adapter->dev, NULL); + adapter->dev, mac); } #endif diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 0951d68e4c..69a2ee47fe 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -440,7 +440,15 @@ void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq, * Return: true or false based on findings */ bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length); -int wlan_hdd_del_station(struct hdd_adapter *adapter); + +/** + * wlan_hdd_del_station() - delete station wrapper + * @adapter: pointer to the hdd adapter + * @mac: pointer to mac addr + * + * Return: Errno + */ +int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac); #if defined(USE_CFG80211_DEL_STA_V2) int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 976bf8a578..1ef079b137 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -6211,7 +6211,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, hdd_abort_ongoing_sta_connection(hdd_ctx); if (adapter->device_mode == QDF_SAP_MODE) { - wlan_hdd_del_station(adapter); + wlan_hdd_del_station(adapter, NULL); mac_handle = hdd_ctx->mac_handle; status = wlan_hdd_flush_pmksa_cache(adapter); if (QDF_IS_STATUS_ERROR(status)) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index dbb3687526..fb48e52aa6 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -7719,7 +7719,7 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx, hdd_abort_ongoing_sta_connection(hdd_ctx); /* Diassociate with all the peers before stop ap post */ if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { - if (wlan_hdd_del_station(adapter)) + if (wlan_hdd_del_station(adapter, NULL)) hdd_sap_indicate_disconnect_for_sta(adapter); } status = wlan_hdd_flush_pmksa_cache(adapter); @@ -16051,7 +16051,7 @@ void wlan_hdd_stop_sap(struct hdd_adapter *ap_adapter) mutex_lock(&hdd_ctx->sap_lock); if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { - wlan_hdd_del_station(ap_adapter); + wlan_hdd_del_station(ap_adapter, NULL); hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter); hdd_debug("Now doing SAP STOPBSS"); qdf_event_reset(&hostapd_state->qdf_stop_bss_event); @@ -18511,7 +18511,7 @@ void hdd_restart_sap(struct hdd_adapter *ap_adapter) mutex_lock(&hdd_ctx->sap_lock); if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { - wlan_hdd_del_station(ap_adapter); + wlan_hdd_del_station(ap_adapter, NULL); hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter); qdf_event_reset(&hostapd_state->qdf_stop_bss_event); if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) { diff --git a/core/hdd/src/wlan_hdd_son.c b/core/hdd/src/wlan_hdd_son.c index 1b99ed4d2b..3d1784f0eb 100644 --- a/core/hdd/src/wlan_hdd_son.c +++ b/core/hdd/src/wlan_hdd_son.c @@ -862,11 +862,252 @@ static enum ieee80211_phymode hdd_son_get_phymode(struct wlan_objmgr_vdev *vdev) hdd_err("null hdd ctx"); return IEEE80211_MODE_AUTO; } + phymode = sme_get_phy_mode(hdd_ctx->mac_handle); return hdd_phymode_chwidth_freq_to_son_phymode(phymode, chwidth, freq); } +/** + * hdd_son_set_acl_policy() - set son acl policy + * @vdev: vdev + * @son_acl_policy: enum ieee80211_acl_cmd + * + * Return: QDF_STATUS + */ +static QDF_STATUS hdd_son_set_acl_policy(struct wlan_objmgr_vdev *vdev, + ieee80211_acl_cmd son_acl_policy) +{ + struct hdd_adapter *adapter; + QDF_STATUS status = QDF_STATUS_E_INVAL; + + if (!vdev) { + hdd_err("null vdev"); + return status; + } + adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + if (!adapter) { + hdd_err("null adapter"); + return status; + } + + switch (son_acl_policy) { + case IEEE80211_MACCMD_POLICY_OPEN: + status = wlansap_set_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + eSAP_ALLOW_ALL); + break; + case IEEE80211_MACCMD_POLICY_ALLOW: + status = wlansap_set_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + eSAP_DENY_UNLESS_ACCEPTED); + break; + case IEEE80211_MACCMD_POLICY_DENY: + status = wlansap_set_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + eSAP_ACCEPT_UNLESS_DENIED); + break; + case IEEE80211_MACCMD_FLUSH: + case IEEE80211_MACCMD_DETACH: + status = wlansap_clear_acl(WLAN_HDD_GET_SAP_CTX_PTR(adapter)); + break; + default: + hdd_err("invalid son acl policy %d", son_acl_policy); + break; + } + + return status; +} + +/** + * hdd_acl_policy_to_son_acl_policy() - convert acl policy to son acl policy + * @acl_policy: acl policy + * + * Return: son acl policy. enum ieee80211_acl_cmd + */ +static ieee80211_acl_cmd hdd_acl_policy_to_son_acl_policy( + eSapMacAddrACL acl_policy) +{ + ieee80211_acl_cmd son_acl_policy = IEEE80211_MACCMD_DETACH; + + switch (acl_policy) { + case eSAP_ACCEPT_UNLESS_DENIED: + son_acl_policy = IEEE80211_MACCMD_POLICY_DENY; + break; + case eSAP_DENY_UNLESS_ACCEPTED: + son_acl_policy = IEEE80211_MACCMD_POLICY_ALLOW; + break; + case eSAP_ALLOW_ALL: + son_acl_policy = IEEE80211_MACCMD_POLICY_OPEN; + break; + default: + hdd_err("invalid acl policy %d", acl_policy); + break; + } + + return son_acl_policy; +} + +/** + * hdd_son_get_acl_policy() - get son acl policy + * @vdev: vdev + * + * Return: son acl policy. enum ieee80211_acl_cmd + */ +static ieee80211_acl_cmd hdd_son_get_acl_policy(struct wlan_objmgr_vdev *vdev) +{ + eSapMacAddrACL acl_policy; + struct hdd_adapter *adapter; + ieee80211_acl_cmd son_acl_policy = IEEE80211_MACCMD_DETACH; + + if (!vdev) { + hdd_err("null vdev"); + return son_acl_policy; + } + adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + if (!adapter) { + hdd_err("null adapter"); + return son_acl_policy; + } + + wlansap_get_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter), &acl_policy); + + son_acl_policy = hdd_acl_policy_to_son_acl_policy(acl_policy); + + return son_acl_policy; +} + +/** + * hdd_son_add_acl_mac() - add mac to access control list(ACL) + * @vdev: vdev + * @acl_mac: mac address to add + * + * Return: 0 on success, negative errno on failure + */ +static int hdd_son_add_acl_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac) +{ + eSapACLType list_type; + QDF_STATUS qdf_status; + eSapMacAddrACL acl_policy; + struct hdd_adapter *adapter; + + if (!vdev) { + hdd_err("null vdev"); + return -EINVAL; + } + if (!acl_mac) { + hdd_err("null acl_mac"); + return -EINVAL; + } + adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + if (!adapter) { + hdd_err("null adapter"); + return -EINVAL; + } + + wlansap_get_acl_mode(WLAN_HDD_GET_SAP_CTX_PTR(adapter), &acl_policy); + + if (acl_policy == eSAP_ACCEPT_UNLESS_DENIED) { + list_type = eSAP_BLACK_LIST; + } else if (acl_policy == eSAP_DENY_UNLESS_ACCEPTED) { + list_type = eSAP_WHITE_LIST; + } else { + hdd_err("Invalid ACL policy %d.", acl_policy); + return -EINVAL; + } + qdf_status = wlansap_modify_acl(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + acl_mac->bytes, list_type, + ADD_STA_TO_ACL); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + hdd_err("Modify ACL failed"); + return -EIO; + } + + return 0; +} + +/** + * hdd_son_del_acl_mac() - delete mac from acl + * @vdev: vdev + * @acl_mac: mac to remove + * + * Return: 0 on success, negative errno on failure + */ +static int hdd_son_del_acl_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac) +{ + eSapACLType list_type; + QDF_STATUS qdf_status; + eSapMacAddrACL acl_policy; + struct hdd_adapter *adapter; + struct sap_context *sap_ctx; + + if (!vdev) { + hdd_err("null vdev"); + return -EINVAL; + } + if (!acl_mac) { + hdd_err("null acl_mac"); + return -EINVAL; + } + adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + if (!adapter) { + hdd_err("null adapter"); + return -EINVAL; + } + + sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter); + if (!sap_ctx) { + hdd_err("null sap ctx"); + return -EINVAL; + } + + wlansap_get_acl_mode(sap_ctx, &acl_policy); + + if (acl_policy == eSAP_ACCEPT_UNLESS_DENIED) { + list_type = eSAP_BLACK_LIST; + } else if (acl_policy == eSAP_DENY_UNLESS_ACCEPTED) { + list_type = eSAP_WHITE_LIST; + } else { + hdd_err("Invalid ACL policy %d.", acl_policy); + return -EINVAL; + } + qdf_status = wlansap_modify_acl(sap_ctx, acl_mac->bytes, list_type, + DELETE_STA_FROM_ACL); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + hdd_err("Modify ACL failed"); + return -EIO; + } + + return 0; +} + +/** + * hdd_son_kickout_mac() - kickout sta with given mac + * @vdev: vdev + * @acl_mac: sta mac to kickout + * + * Return: 0 on success, negative errno on failure + */ +static int hdd_son_kickout_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *mac) +{ + struct hdd_adapter *adapter; + + if (!vdev) { + hdd_err("null vdev"); + return -EINVAL; + } + adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + if (!adapter) { + hdd_err("null adapter"); + return -EINVAL; + } + + if (mac) + return wlan_hdd_del_station(adapter, mac->bytes); + else + return wlan_hdd_del_station(adapter, NULL); +} + static uint8_t hdd_son_get_rx_nss(struct wlan_objmgr_vdev *vdev) { struct hdd_adapter *adapter = wlan_hdd_get_adapter_from_objmgr(vdev); @@ -891,6 +1132,11 @@ void hdd_son_register_callbacks(struct hdd_context *hdd_ctx) cb_obj.os_if_set_bandwidth = hdd_son_set_bandwidth; cb_obj.os_if_get_bandwidth = hdd_son_get_bandwidth; cb_obj.os_if_set_chan = hdd_son_set_chan; + cb_obj.os_if_set_acl_policy = hdd_son_set_acl_policy; + cb_obj.os_if_get_acl_policy = hdd_son_get_acl_policy; + cb_obj.os_if_add_acl_mac = hdd_son_add_acl_mac; + cb_obj.os_if_del_acl_mac = hdd_son_del_acl_mac; + cb_obj.os_if_kickout_mac = hdd_son_kickout_mac; cb_obj.os_if_set_country_code = hdd_son_set_country; cb_obj.os_if_set_candidate_freq = hdd_son_set_candidate_freq; cb_obj.os_if_get_candidate_freq = hdd_son_get_candidate_freq; diff --git a/os_if/son/inc/os_if_son.h b/os_if/son/inc/os_if_son.h index c0f3356abe..f3a7725cf5 100644 --- a/os_if/son/inc/os_if_son.h +++ b/os_if/son/inc/os_if_son.h @@ -46,6 +46,11 @@ * @os_if_set_phymode: set phy mode * @os_if_get_phymode: get phy mode * @os_if_get_rx_nss: Gets number of RX spatial streams + * @os_if_set_acl_policy: set acl policy + * @os_if_get_acl_policy: get acl policy + * @os_if_add_acl_mac: add mac to acl + * @os_if_del_acl_mac: del mac from acl + * @os_if_kickout_mac: kickout sta with given mac */ struct son_callbacks { uint32_t (*os_if_is_acs_in_progress)(struct wlan_objmgr_vdev *vdev); @@ -70,6 +75,16 @@ struct son_callbacks { enum ieee80211_phymode (*os_if_get_phymode)( struct wlan_objmgr_vdev *vdev); uint8_t (*os_if_get_rx_nss)(struct wlan_objmgr_vdev *vdev); + QDF_STATUS (*os_if_set_acl_policy)(struct wlan_objmgr_vdev *vdev, + ieee80211_acl_cmd son_acl_policy); + ieee80211_acl_cmd (*os_if_get_acl_policy)( + struct wlan_objmgr_vdev *vdev); + int (*os_if_add_acl_mac)(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac); + int (*os_if_del_acl_mac)(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac); + int (*os_if_kickout_mac)(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac); }; /** @@ -370,4 +385,52 @@ QDF_STATUS os_if_son_cfg80211_reply(qdf_nbuf_t sk_buf); */ bool os_if_son_vdev_is_wds(struct wlan_objmgr_vdev *vdev); +/* + * os_if_son_set_acl_policy() - set acl policy + * @vdev: vdev + * @son_acl_policy: son acl policy. enum ieee80211_acl_cmd + * + * Return: QDF_STATUS + */ +QDF_STATUS os_if_son_set_acl_policy(struct wlan_objmgr_vdev *vdev, + ieee80211_acl_cmd son_acl_policy); + +/** + * os_if_son_get_acl_policy() - get acl policy + * @vdev: vdev + * + * Return: acl policy. enum ieee80211_acl_cmd + */ +ieee80211_acl_cmd os_if_son_get_acl_policy(struct wlan_objmgr_vdev *vdev); + +/** + * os_if_son_add_acl_mac() - add mac to acl + * @vdev: vdev + * @acl_mac: mac to add + * + * Return: 0 on success, negative errno on failure + */ +int os_if_son_add_acl_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac); + +/** + * os_if_son_del_acl_mac() - del mac from acl + * @vdev: vdev + * @acl_mac: mac to del + * + * Return: 0 on success, negative errno on failure + */ +int os_if_son_del_acl_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac); + +/** + * os_if_son_kickout_mac() - kickout sta with given mac + * @vdev: vdev + * @acl_mac: sta mac to kickout + * + * Return: 0 on success, negative errno on failure + */ +int os_if_son_kickout_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *mac); + #endif diff --git a/os_if/son/src/os_if_son.c b/os_if/son/src/os_if_son.c index d70aff68b3..00808ab824 100644 --- a/os_if/son/src/os_if_son.c +++ b/os_if/son/src/os_if_son.c @@ -625,6 +625,89 @@ qdf_freq_t os_if_son_get_candidate_freq(struct wlan_objmgr_vdev *vdev) } qdf_export_symbol(os_if_son_get_candidate_freq); +QDF_STATUS os_if_son_set_acl_policy(struct wlan_objmgr_vdev *vdev, + ieee80211_acl_cmd son_acl_policy) +{ + QDF_STATUS ret; + + if (!vdev) { + osif_err("null vdev"); + return QDF_STATUS_E_INVAL; + } + + ret = g_son_os_if_cb.os_if_set_acl_policy(vdev, son_acl_policy); + osif_debug("set acl policy %d status %d", son_acl_policy, ret); + + return ret; +} +qdf_export_symbol(os_if_son_set_acl_policy); + +ieee80211_acl_cmd os_if_son_get_acl_policy(struct wlan_objmgr_vdev *vdev) +{ + ieee80211_acl_cmd son_acl_policy; + + if (!vdev) { + osif_err("null vdev"); + return IEEE80211_MACCMD_DETACH; + } + son_acl_policy = g_son_os_if_cb.os_if_get_acl_policy(vdev); + osif_debug("get acl policy %d", son_acl_policy); + + return son_acl_policy; +} +qdf_export_symbol(os_if_son_get_acl_policy); + +int os_if_son_add_acl_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac) +{ + int ret; + + if (!vdev) { + osif_err("null vdev"); + return -EINVAL; + } + ret = g_son_os_if_cb.os_if_add_acl_mac(vdev, acl_mac); + osif_debug("add_acl_mac " QDF_MAC_ADDR_FMT " ret %d", + QDF_MAC_ADDR_REF(acl_mac->bytes), ret); + + return ret; +} +qdf_export_symbol(os_if_son_add_acl_mac); + +int os_if_son_del_acl_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *acl_mac) +{ + int ret; + + if (!vdev) { + osif_err("null vdev"); + return -EINVAL; + } + ret = g_son_os_if_cb.os_if_del_acl_mac(vdev, acl_mac); + osif_debug("del_acl_mac " QDF_MAC_ADDR_FMT " ret %d", + QDF_MAC_ADDR_REF(acl_mac->bytes), ret); + + return ret; +} +qdf_export_symbol(os_if_son_del_acl_mac); + +int os_if_son_kickout_mac(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *mac) +{ + int ret; + + if (!vdev) { + osif_err("null vdev"); + return -EINVAL; + } + ret = g_son_os_if_cb.os_if_kickout_mac(vdev, mac); + osif_debug("kickout mac " QDF_MAC_ADDR_FMT " ret %d", + QDF_MAC_ADDR_REF(mac->bytes), ret); + + return ret; +} +qdf_export_symbol(os_if_son_kickout_mac); + int os_if_son_set_phymode(struct wlan_objmgr_vdev *vdev, enum ieee80211_phymode mode) {