@@ -1621,6 +1621,64 @@ static int mwifiex_cfg80211_set_txq_params(struct wiphy *wiphy,
return 0;
}
+/* cfg80211 operation handler for set_mac_acl.
+ * function sets station mac address filter params to FW.
+ */
+static int mwifiex_cfg80211_set_mac_acl(struct wiphy *wiphy,
+ struct net_device *dev,
+ const struct cfg80211_acl_data *params)
+{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ struct mwifiex_ds_mac_filter *mac_filter;
+
+ if (!priv || !params)
+ return -EINVAL;
+
+ if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
+ wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__);
+ return -EINVAL;
+ }
+
+ mac_filter = kzalloc(sizeof(*mac_filter), GFP_KERNEL);
+ if (!mac_filter)
+ return -ENOMEM;
+
+ wiphy_dbg(wiphy, "set_mac_acl, n_acl_entries=%d, acl_policy=%d\n",
+ params->n_acl_entries, params->acl_policy);
+
+ mac_filter->mac_count = (params->n_acl_entries <=
+ MWIFIEX_MAX_MAC_FILTER_NUM) ?
+ params->n_acl_entries :
+ MWIFIEX_MAX_MAC_FILTER_NUM;
+
+ switch (params->acl_policy) {
+ case NL80211_ACL_POLICY_DENY_UNLESS_LISTED:
+ mac_filter->filter_mode = MWIFIEX_MAC_FILTER_MODE_ALLOW_MAC;
+ break;
+ case NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED:
+ mac_filter->filter_mode = MWIFIEX_MAC_FILTER_MODE_BLOCK_MAC;
+ break;
+ default:
+ wiphy_err(wiphy, "unknown ACL policy\n");
+ kfree(mac_filter);
+ return -EINVAL;
+ }
+
+ memcpy(mac_filter->mac_list, params->mac_addrs,
+ sizeof(struct mac_address) * mac_filter->mac_count);
+
+ if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
+ HostCmd_ACT_GEN_SET,
+ UAP_MAC_FILTER_I, mac_filter, false)) {
+ wiphy_err(wiphy, "Failed to set AP mac acl params\n");
+ kfree(mac_filter);
+ return -1;
+ }
+
+ kfree(mac_filter);
+ return 0;
+}
+
/* cfg80211 operation handler for del_station.
* Function deauthenticates station which value is provided in mac parameter.
* If mac is NULL/broadcast, all stations in associated station list are
@@ -3374,6 +3432,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
.stop_ap = mwifiex_cfg80211_stop_ap,
.change_beacon = mwifiex_cfg80211_change_beacon,
.set_txq_params = mwifiex_cfg80211_set_txq_params,
+ .set_mac_acl = mwifiex_cfg80211_set_mac_acl,
.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
.set_antenna = mwifiex_cfg80211_set_antenna,
.del_station = mwifiex_cfg80211_del_station,
@@ -3487,6 +3546,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->cipher_suites = mwifiex_cipher_suites;
wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
+ wiphy->max_acl_mac_addrs = MWIFIEX_MAX_MAC_FILTER_NUM;
+
ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
@@ -110,6 +110,11 @@
#define MWIFIEX_A_BAND_START_FREQ 5000
+#define MWIFIEX_MAC_FILTER_MODE_DISABLE 0
+#define MWIFIEX_MAC_FILTER_MODE_ALLOW_MAC 1
+#define MWIFIEX_MAC_FILTER_MODE_BLOCK_MAC 2
+#define MWIFIEX_MAX_MAC_FILTER_NUM 16
+
enum mwifiex_bss_type {
MWIFIEX_BSS_TYPE_STA = 0,
MWIFIEX_BSS_TYPE_UAP = 1,
@@ -117,6 +117,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define UAP_BSS_PARAMS_I 0
#define UAP_CUSTOM_IE_I 1
#define UAP_WMM_PARAMS_I 2
+#define UAP_MAC_FILTER_I 3
#define MWIFIEX_AUTO_IDX_MASK 0xffff
#define MWIFIEX_DELETE_MASK 0x0000
#define MGMT_MASK_ASSOC_REQ 0x01
@@ -148,6 +149,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45)
#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48)
#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51)
+#define TLV_TYPE_UAP_MAC_FILTER (PROPRIETARY_TLV_BASE_ID + 56)
#define TLV_TYPE_UAP_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 57)
#define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 59)
#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60)
@@ -1553,6 +1555,13 @@ struct mwifiex_ie_types_wmmcap {
struct mwifiex_types_wmm_info wmm_info;
} __packed;
+struct mwifiex_ie_types_mac_filter {
+ struct mwifiex_ie_types_header header;
+ u8 filter_mode;
+ u8 mac_count;
+ u8 mac_list[0];
+} __packed;
+
struct mwifiex_ie_types_htinfo {
struct mwifiex_ie_types_header header;
struct ieee80211_ht_operation ht_oper;
@@ -402,6 +402,12 @@ struct mwifiex_ds_mef_cfg {
struct mwifiex_mef_entry *mef_entry;
};
+struct mwifiex_ds_mac_filter {
+ u8 filter_mode;
+ u8 mac_count;
+ struct mac_address mac_list[MWIFIEX_MAX_MAC_FILTER_NUM];
+};
+
#define MWIFIEX_MAX_VSIE_LEN (256)
#define MWIFIEX_MAX_VSIE_NUM (8)
#define MWIFIEX_VSIE_MASK_CLEAR 0x00
@@ -677,6 +677,27 @@ static int mwifiex_uap_wmm_ie_prepare(u8 *tlv, void *cmd_buf, u16 *cmd_size)
return 0;
}
+/* This function prepare mac address filter tlv */
+static int
+mwifiex_uap_mac_filter_prepare(u8 *tlv, void *cmd_buf, u16 *cmd_size)
+{
+ struct mwifiex_ds_mac_filter *mac_acl = cmd_buf;
+ struct mwifiex_ie_types_mac_filter *mac_filter = (void *)tlv;
+
+ mac_filter->header.type = cpu_to_le16(TLV_TYPE_UAP_MAC_FILTER);
+ mac_filter->filter_mode = mac_acl->filter_mode;
+ mac_filter->mac_count = mac_acl->mac_count;
+ memcpy(&mac_filter->mac_list, mac_acl->mac_list,
+ ETH_ALEN * mac_filter->mac_count);
+ mac_filter->header.len =
+ cpu_to_le16(sizeof(mac_filter->filter_mode) +
+ sizeof(mac_filter->mac_count) +
+ ETH_ALEN * mac_filter->mac_count);
+ *cmd_size += sizeof(*mac_filter) + ETH_ALEN * mac_filter->mac_count;
+
+ return 0;
+}
+
/* This function parses custom IEs from IE list and prepares command buffer */
static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
{
@@ -732,6 +753,10 @@ mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
mwifiex_uap_wmm_ie_prepare(tlv, cmd_buf, &cmd_size);
cmd->size = cpu_to_le16(cmd_size);
break;
+ case UAP_MAC_FILTER_I:
+ mwifiex_uap_mac_filter_prepare(tlv, cmd_buf, &cmd_size);
+ cmd->size = cpu_to_le16(cmd_size);
+ break;
default:
return -1;
}