From: Xinming Hu <huxm@xxxxxxxxxxx> This patch add cfg80211 set_mac_acl handler for AP mode, this handler will be used by user space application to configure accept/deny mac address list throgh nl80211/cfg80211. Signed-off-by: Xinming Hu <huxm@xxxxxxxxxxx> Signed-off-by: Cathy Luo <cluo@xxxxxxxxxxx> Signed-off-by: Avinash Patil <patila@xxxxxxxxxxx> --- drivers/net/wireless/mwifiex/cfg80211.c | 61 +++++++++++++++++++++++++++++++++ drivers/net/wireless/mwifiex/decl.h | 5 +++ drivers/net/wireless/mwifiex/fw.h | 9 +++++ drivers/net/wireless/mwifiex/ioctl.h | 6 ++++ drivers/net/wireless/mwifiex/uap_cmd.c | 25 ++++++++++++++ 5 files changed, 106 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index f933159..d1a684a 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -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 | diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 0059d6f..b364a2c 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -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, diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 2a38964..408c1eb 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -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; diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 9795220..4d51775 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -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 diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 82e4797..0cffcb9 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -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; } -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html