hostapd: Support MAC address based access control list
Enable MAC address based ACL for the drivers which advertise this capabilty with NL80211_ATTR_MAC_ACL_MAX. Either of blacklist or whitelist is supported, though, not simultaneously. Signed-hostap: Vivek Natarajan <nataraja@qca.qualcomm.com>
This commit is contained in:
parent
376204934d
commit
3c4ca36330
4 changed files with 157 additions and 0 deletions
|
@ -173,6 +173,14 @@ static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
|
||||||
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
|
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int hostapd_drv_set_acl(struct hostapd_data *hapd,
|
||||||
|
struct hostapd_acl_params *params)
|
||||||
|
{
|
||||||
|
if (hapd->driver == NULL || hapd->driver->set_acl == NULL)
|
||||||
|
return 0;
|
||||||
|
return hapd->driver->set_acl(hapd->drv_priv, params);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
|
static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
|
||||||
struct wpa_driver_ap_params *params)
|
struct wpa_driver_ap_params *params)
|
||||||
{
|
{
|
||||||
|
|
|
@ -837,6 +837,72 @@ static void hostapd_tx_queue_params(struct hostapd_iface *iface)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_set_acl_list(struct hostapd_data *hapd,
|
||||||
|
struct mac_acl_entry *mac_acl,
|
||||||
|
int n_entries, u8 accept_acl)
|
||||||
|
{
|
||||||
|
struct hostapd_acl_params *acl_params;
|
||||||
|
int i, err;
|
||||||
|
|
||||||
|
acl_params = os_zalloc(sizeof(*acl_params) +
|
||||||
|
(n_entries * sizeof(acl_params->mac_acl[0])));
|
||||||
|
if (!acl_params)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0; i < n_entries; i++)
|
||||||
|
os_memcpy(acl_params->mac_acl[i].addr, mac_acl[i].addr,
|
||||||
|
ETH_ALEN);
|
||||||
|
|
||||||
|
acl_params->acl_policy = accept_acl;
|
||||||
|
acl_params->num_mac_acl = n_entries;
|
||||||
|
|
||||||
|
err = hostapd_drv_set_acl(hapd, acl_params);
|
||||||
|
|
||||||
|
os_free(acl_params);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_set_acl(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
struct hostapd_config *conf = hapd->iconf;
|
||||||
|
int err;
|
||||||
|
u8 accept_acl;
|
||||||
|
|
||||||
|
if (!(conf->bss->num_accept_mac || conf->bss->num_deny_mac))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (conf->bss->macaddr_acl == DENY_UNLESS_ACCEPTED) {
|
||||||
|
if (conf->bss->num_accept_mac) {
|
||||||
|
accept_acl = 1;
|
||||||
|
err = hostapd_set_acl_list(hapd, conf->bss->accept_mac,
|
||||||
|
conf->bss->num_accept_mac,
|
||||||
|
accept_acl);
|
||||||
|
if (err) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Failed to set accept acl");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file");
|
||||||
|
}
|
||||||
|
} else if (conf->bss->macaddr_acl == ACCEPT_UNLESS_DENIED) {
|
||||||
|
if (conf->bss->num_deny_mac) {
|
||||||
|
accept_acl = 0;
|
||||||
|
err = hostapd_set_acl_list(hapd, conf->bss->deny_mac,
|
||||||
|
conf->bss->num_deny_mac,
|
||||||
|
accept_acl);
|
||||||
|
if (err) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Failed to set deny acl");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int setup_interface(struct hostapd_iface *iface)
|
static int setup_interface(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = iface->bss[0];
|
struct hostapd_data *hapd = iface->bss[0];
|
||||||
|
@ -962,6 +1028,8 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
|
||||||
|
|
||||||
ap_list_init(iface);
|
ap_list_init(iface);
|
||||||
|
|
||||||
|
hostapd_set_acl(hapd);
|
||||||
|
|
||||||
if (hostapd_driver_commit(hapd) < 0) {
|
if (hostapd_driver_commit(hapd) < 0) {
|
||||||
wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
|
wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
|
||||||
"configuration", __func__);
|
"configuration", __func__);
|
||||||
|
|
|
@ -906,6 +906,8 @@ struct wpa_driver_capa {
|
||||||
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING 0x00000008
|
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING 0x00000008
|
||||||
unsigned int probe_resp_offloads;
|
unsigned int probe_resp_offloads;
|
||||||
|
|
||||||
|
unsigned int max_acl_mac_addrs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* extended_capa - extended capabilities in driver/device
|
* extended_capa - extended capabilities in driver/device
|
||||||
*
|
*
|
||||||
|
@ -966,6 +968,16 @@ struct hostapd_freq_params {
|
||||||
int bandwidth;
|
int bandwidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mac_address {
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hostapd_acl_params {
|
||||||
|
u8 acl_policy;
|
||||||
|
unsigned int num_mac_acl;
|
||||||
|
struct mac_address mac_acl[0];
|
||||||
|
};
|
||||||
|
|
||||||
enum wpa_driver_if_type {
|
enum wpa_driver_if_type {
|
||||||
/**
|
/**
|
||||||
* WPA_IF_STATION - Station mode interface
|
* WPA_IF_STATION - Station mode interface
|
||||||
|
@ -1595,6 +1607,16 @@ struct wpa_driver_ops {
|
||||||
*/
|
*/
|
||||||
int (*set_ap)(void *priv, struct wpa_driver_ap_params *params);
|
int (*set_ap)(void *priv, struct wpa_driver_ap_params *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set_acl - Set ACL in AP mode
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @params: Parameters to configure ACL
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This is used only for the drivers which support MAC address ACL.
|
||||||
|
*/
|
||||||
|
int (*set_acl)(void *priv, struct hostapd_acl_params *params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hapd_init - Initialize driver interface (hostapd only)
|
* hapd_init - Initialize driver interface (hostapd only)
|
||||||
* @hapd: Pointer to hostapd context
|
* @hapd: Pointer to hostapd context
|
||||||
|
|
|
@ -2862,6 +2862,10 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
||||||
capa->max_match_sets =
|
capa->max_match_sets =
|
||||||
nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
|
nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
|
||||||
|
|
||||||
|
if (tb[NL80211_ATTR_MAC_ACL_MAX])
|
||||||
|
capa->max_acl_mac_addrs =
|
||||||
|
nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
|
||||||
|
|
||||||
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
|
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
|
||||||
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
|
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
|
||||||
wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
|
wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
|
||||||
|
@ -5813,6 +5817,60 @@ static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_nl80211_set_acl(void *priv,
|
||||||
|
struct hostapd_acl_params *params)
|
||||||
|
{
|
||||||
|
struct i802_bss *bss = priv;
|
||||||
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
struct nl_msg *msg;
|
||||||
|
struct nlattr *acl;
|
||||||
|
unsigned int i;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!(drv->capa.max_acl_mac_addrs))
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
msg = nlmsg_alloc();
|
||||||
|
if (!msg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
|
||||||
|
params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
|
||||||
|
|
||||||
|
nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_MAC_ACL);
|
||||||
|
|
||||||
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
||||||
|
|
||||||
|
NLA_PUT_U32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
|
||||||
|
NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
|
||||||
|
NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED);
|
||||||
|
|
||||||
|
acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
|
||||||
|
if (acl == NULL)
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
for (i = 0; i < params->num_mac_acl; i++)
|
||||||
|
NLA_PUT(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr);
|
||||||
|
|
||||||
|
nla_nest_end(msg, acl);
|
||||||
|
|
||||||
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
|
msg = NULL;
|
||||||
|
if (ret) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
|
||||||
|
ret, strerror(-ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
nla_put_failure:
|
||||||
|
nlmsg_free(msg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_nl80211_set_ap(void *priv,
|
static int wpa_driver_nl80211_set_ap(void *priv,
|
||||||
struct wpa_driver_ap_params *params)
|
struct wpa_driver_ap_params *params)
|
||||||
{
|
{
|
||||||
|
@ -9882,6 +9940,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.set_supp_port = wpa_driver_nl80211_set_supp_port,
|
.set_supp_port = wpa_driver_nl80211_set_supp_port,
|
||||||
.set_country = wpa_driver_nl80211_set_country,
|
.set_country = wpa_driver_nl80211_set_country,
|
||||||
.set_ap = wpa_driver_nl80211_set_ap,
|
.set_ap = wpa_driver_nl80211_set_ap,
|
||||||
|
.set_acl = wpa_driver_nl80211_set_acl,
|
||||||
.if_add = wpa_driver_nl80211_if_add,
|
.if_add = wpa_driver_nl80211_if_add,
|
||||||
.if_remove = driver_nl80211_if_remove,
|
.if_remove = driver_nl80211_if_remove,
|
||||||
.send_mlme = driver_nl80211_send_mlme,
|
.send_mlme = driver_nl80211_send_mlme,
|
||||||
|
|
Loading…
Reference in a new issue