wifi: cfg80211/mac80211: Support control port TX from specific link
In case of authentication with a legacy station, link addressed EAPOL frames should be sent. Support it. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
d2bc52498b
commit
67207bab93
6 changed files with 35 additions and 12 deletions
|
@ -4580,7 +4580,7 @@ struct cfg80211_ops {
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
const u8 *buf, size_t len,
|
const u8 *buf, size_t len,
|
||||||
const u8 *dest, const __be16 proto,
|
const u8 *dest, const __be16 proto,
|
||||||
const bool noencrypt,
|
const bool noencrypt, int link_id,
|
||||||
u64 *cookie);
|
u64 *cookie);
|
||||||
|
|
||||||
int (*get_ftm_responder_stats)(struct wiphy *wiphy,
|
int (*get_ftm_responder_stats)(struct wiphy *wiphy,
|
||||||
|
|
|
@ -1946,7 +1946,7 @@ void ieee80211_clear_fast_xmit(struct sta_info *sta);
|
||||||
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||||
const u8 *buf, size_t len,
|
const u8 *buf, size_t len,
|
||||||
const u8 *dest, __be16 proto, bool unencrypted,
|
const u8 *dest, __be16 proto, bool unencrypted,
|
||||||
u64 *cookie);
|
int link_id, u64 *cookie);
|
||||||
int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
|
int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
|
||||||
const u8 *buf, size_t len);
|
const u8 *buf, size_t len);
|
||||||
|
|
||||||
|
|
|
@ -5674,7 +5674,7 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
|
||||||
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||||
const u8 *buf, size_t len,
|
const u8 *buf, size_t len,
|
||||||
const u8 *dest, __be16 proto, bool unencrypted,
|
const u8 *dest, __be16 proto, bool unencrypted,
|
||||||
u64 *cookie)
|
int link_id, u64 *cookie)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
@ -5714,7 +5714,23 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
||||||
|
|
||||||
ehdr = skb_push(skb, sizeof(struct ethhdr));
|
ehdr = skb_push(skb, sizeof(struct ethhdr));
|
||||||
memcpy(ehdr->h_dest, dest, ETH_ALEN);
|
memcpy(ehdr->h_dest, dest, ETH_ALEN);
|
||||||
|
|
||||||
|
if (link_id < 0) {
|
||||||
memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
|
memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
|
||||||
|
} else {
|
||||||
|
struct ieee80211_bss_conf *link_conf;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
link_conf = rcu_dereference(sdata->vif.link_conf[link_id]);
|
||||||
|
if (!link_conf) {
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
rcu_read_unlock();
|
||||||
|
return -ENOLINK;
|
||||||
|
}
|
||||||
|
memcpy(ehdr->h_source, link_conf->addr, ETH_ALEN);
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
ehdr->h_proto = proto;
|
ehdr->h_proto = proto;
|
||||||
|
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
|
|
|
@ -15223,6 +15223,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
|
||||||
u16 proto;
|
u16 proto;
|
||||||
bool noencrypt;
|
bool noencrypt;
|
||||||
u64 cookie = 0;
|
u64 cookie = 0;
|
||||||
|
int link_id;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||||
|
@ -15271,8 +15272,10 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
|
||||||
noencrypt =
|
noencrypt =
|
||||||
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
|
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
|
||||||
|
|
||||||
|
link_id = nl80211_link_id_or_invalid(info->attrs);
|
||||||
|
|
||||||
err = rdev_tx_control_port(rdev, dev, buf, len,
|
err = rdev_tx_control_port(rdev, dev, buf, len,
|
||||||
dest, cpu_to_be16(proto), noencrypt,
|
dest, cpu_to_be16(proto), noencrypt, link_id,
|
||||||
dont_wait_for_ack ? NULL : &cookie);
|
dont_wait_for_ack ? NULL : &cookie);
|
||||||
if (!err && !dont_wait_for_ack)
|
if (!err && !dont_wait_for_ack)
|
||||||
nl_set_extack_cookie_u64(info->extack, cookie);
|
nl_set_extack_cookie_u64(info->extack, cookie);
|
||||||
|
|
|
@ -746,13 +746,14 @@ static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
const void *buf, size_t len,
|
const void *buf, size_t len,
|
||||||
const u8 *dest, __be16 proto,
|
const u8 *dest, __be16 proto,
|
||||||
const bool noencrypt, u64 *cookie)
|
const bool noencrypt, int link,
|
||||||
|
u64 *cookie)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
|
trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
|
||||||
dest, proto, noencrypt);
|
dest, proto, noencrypt, link);
|
||||||
ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
|
ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
|
||||||
dest, proto, noencrypt, cookie);
|
dest, proto, noencrypt, link, cookie);
|
||||||
if (cookie)
|
if (cookie)
|
||||||
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
|
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
|
||||||
else
|
else
|
||||||
|
|
|
@ -2015,14 +2015,15 @@ TRACE_EVENT(rdev_mgmt_tx,
|
||||||
TRACE_EVENT(rdev_tx_control_port,
|
TRACE_EVENT(rdev_tx_control_port,
|
||||||
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
|
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
|
||||||
const u8 *buf, size_t len, const u8 *dest, __be16 proto,
|
const u8 *buf, size_t len, const u8 *dest, __be16 proto,
|
||||||
bool unencrypted),
|
bool unencrypted, int link_id),
|
||||||
TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted),
|
TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted, link_id),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
WIPHY_ENTRY
|
WIPHY_ENTRY
|
||||||
NETDEV_ENTRY
|
NETDEV_ENTRY
|
||||||
MAC_ENTRY(dest)
|
MAC_ENTRY(dest)
|
||||||
__field(__be16, proto)
|
__field(__be16, proto)
|
||||||
__field(bool, unencrypted)
|
__field(bool, unencrypted)
|
||||||
|
__field(int, link_id)
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
|
@ -2030,12 +2031,14 @@ TRACE_EVENT(rdev_tx_control_port,
|
||||||
MAC_ASSIGN(dest, dest);
|
MAC_ASSIGN(dest, dest);
|
||||||
__entry->proto = proto;
|
__entry->proto = proto;
|
||||||
__entry->unencrypted = unencrypted;
|
__entry->unencrypted = unencrypted;
|
||||||
|
__entry->link_id = link_id;
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ","
|
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ","
|
||||||
" proto: 0x%x, unencrypted: %s",
|
" proto: 0x%x, unencrypted: %s, link: %d",
|
||||||
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest),
|
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest),
|
||||||
be16_to_cpu(__entry->proto),
|
be16_to_cpu(__entry->proto),
|
||||||
BOOL_TO_STR(__entry->unencrypted))
|
BOOL_TO_STR(__entry->unencrypted),
|
||||||
|
__entry->link_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(rdev_set_noack_map,
|
TRACE_EVENT(rdev_set_noack_map,
|
||||||
|
|
Loading…
Add table
Reference in a new issue