Commit 8c3ed7aa authored by Markus Theil's avatar Markus Theil Committed by Johannes Berg

nl80211: add src and dst addr attributes for control port tx/rx

When using control port over nl80211 in AP mode with
pre-authentication, APs need to forward frames to other
APs defined by their MAC address. Before this patch,
pre-auth frames reaching user space over nl80211 control
port  have no longer any information about the dest attached,
which can be used for forwarding to a controller or injecting
the frame back to a ethernet interface over a AF_PACKET
socket.
Analog problems exist, when forwarding pre-auth frames from
AP -> STA.

This patch therefore adds the NL80211_ATTR_DST_MAC and
NL80211_ATTR_SRC_MAC attributes to provide more context
information when forwarding.
The respective arguments are optional on tx and included on rx.
Therefore unaware existing software is not affected.

Software which wants to detect this feature, can do so
by checking against:
  NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS
Signed-off-by: default avatarMarkus Theil <markus.theil@tu-ilmenau.de>
Link: https://lore.kernel.org/r/20200115125522.3755-1-markus.theil@tu-ilmenau.de
[split into separate cfg80211/mac80211 patches]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c0058df7
...@@ -3969,7 +3969,8 @@ struct cfg80211_ops { ...@@ -3969,7 +3969,8 @@ struct cfg80211_ops {
int (*tx_control_port)(struct wiphy *wiphy, int (*tx_control_port)(struct wiphy *wiphy,
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 u8 *src,
const __be16 proto,
const bool noencrypt); const bool noencrypt);
int (*get_ftm_responder_stats)(struct wiphy *wiphy, int (*get_ftm_responder_stats)(struct wiphy *wiphy,
......
...@@ -1039,11 +1039,14 @@ ...@@ -1039,11 +1039,14 @@
* a control port frame and as a notification that a control port frame * a control port frame and as a notification that a control port frame
* has been received. %NL80211_ATTR_FRAME is used to specify the * has been received. %NL80211_ATTR_FRAME is used to specify the
* frame contents. The frame is the raw EAPoL data, without ethernet or * frame contents. The frame is the raw EAPoL data, without ethernet or
* 802.11 headers. * 802.11 headers. An optional %NL80211_ATTR_SRC_MAC can be used to send
* pre-auth frames to STAs on behalf of other APs.
* When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, * When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added
* indicating the protocol type of the received frame; whether the frame * indicating the protocol type of the received frame; whether the frame
* was received unencrypted and the MAC address of the peer respectively. * was received unencrypted and the MAC address of the peer respectively.
* %NL80211_ATTR_DST_MAC can be used to forward pre-auth frames in
* userspace while using AP mode.
* *
* @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
* *
...@@ -2409,6 +2412,9 @@ enum nl80211_commands { ...@@ -2409,6 +2412,9 @@ enum nl80211_commands {
* %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not * %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not
* advertised for a specific interface type. * advertised for a specific interface type.
* *
* @NL80211_ATTR_SRC_MAC: MAC address used in control port over nl80211 transmit
* @NL80211_ATTR_DST_MAC: MAC address used in control port over nl80211 receive
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
...@@ -2877,6 +2883,9 @@ enum nl80211_attrs { ...@@ -2877,6 +2883,9 @@ enum nl80211_attrs {
NL80211_ATTR_IFTYPE_AKM_SUITES, NL80211_ATTR_IFTYPE_AKM_SUITES,
NL80211_ATTR_SRC_MAC,
NL80211_ATTR_DST_MAC,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, __NL80211_ATTR_AFTER_LAST,
...@@ -5539,6 +5548,10 @@ enum nl80211_feature_flags { ...@@ -5539,6 +5548,10 @@ enum nl80211_feature_flags {
* feature, which prevents bufferbloat by using the expected transmission * feature, which prevents bufferbloat by using the expected transmission
* time to limit the amount of data buffered in the hardware. * time to limit the amount of data buffered in the hardware.
* *
* @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS: The driver
* can use src and dst MAC addresses with control port over nl80211 rx
* and tx operations.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features. * @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index. * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/ */
...@@ -5586,6 +5599,7 @@ enum nl80211_ext_feature_index { ...@@ -5586,6 +5599,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_SAE_OFFLOAD, NL80211_EXT_FEATURE_SAE_OFFLOAD,
NL80211_EXT_FEATURE_VLAN_OFFLOAD, NL80211_EXT_FEATURE_VLAN_OFFLOAD,
NL80211_EXT_FEATURE_AQL, NL80211_EXT_FEATURE_AQL,
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS,
/* add new features before the definition below */ /* add new features before the definition below */
NUM_NL80211_EXT_FEATURES, NUM_NL80211_EXT_FEATURES,
......
...@@ -1792,7 +1792,8 @@ void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata); ...@@ -1792,7 +1792,8 @@ void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata);
void ieee80211_clear_fast_xmit(struct sta_info *sta); 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, const u8 *src, __be16 proto,
bool unencrypted);
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);
......
...@@ -5285,7 +5285,8 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, ...@@ -5285,7 +5285,8 @@ void __ieee80211_tx_skb_tid_band(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, const u8 *src, __be16 proto,
bool unencrypted)
{ {
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;
......
...@@ -633,6 +633,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { ...@@ -633,6 +633,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy), [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
[NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2), [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
[NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy), [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
[NL80211_ATTR_SRC_MAC] = NLA_POLICY_ETH_ADDR,
[NL80211_ATTR_DST_MAC] = NLA_POLICY_ETH_ADDR,
}; };
/* policy for the key attributes */ /* policy for the key attributes */
...@@ -13694,6 +13696,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info) ...@@ -13694,6 +13696,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
const u8 *buf; const u8 *buf;
size_t len; size_t len;
u8 *dest; u8 *dest;
u8 src[ETH_ALEN];
u16 proto; u16 proto;
bool noencrypt; bool noencrypt;
int err; int err;
...@@ -13731,6 +13734,13 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info) ...@@ -13731,6 +13734,13 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
goto out; goto out;
} }
/* copy src address under wdev_lock, as we may copy wdev_address */
if (info->attrs[NL80211_ATTR_SRC_MAC])
ether_addr_copy(src,
nla_data(info->attrs[NL80211_ATTR_SRC_MAC]));
else
ether_addr_copy(src, wdev_address(wdev));
wdev_unlock(wdev); wdev_unlock(wdev);
buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
...@@ -13741,7 +13751,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info) ...@@ -13741,7 +13751,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]); nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
return rdev_tx_control_port(rdev, dev, buf, len, return rdev_tx_control_port(rdev, dev, buf, len,
dest, cpu_to_be16(proto), noencrypt); dest, src, cpu_to_be16(proto), noencrypt);
out: out:
wdev_unlock(wdev); wdev_unlock(wdev);
...@@ -15996,7 +16006,8 @@ static int __nl80211_rx_control_port(struct net_device *dev, ...@@ -15996,7 +16006,8 @@ static int __nl80211_rx_control_port(struct net_device *dev,
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct ethhdr *ehdr = eth_hdr(skb); struct ethhdr *ehdr = eth_hdr(skb);
const u8 *addr = ehdr->h_source; const u8 *daddr = ehdr->h_dest;
const u8 *saddr = ehdr->h_source;
u16 proto = be16_to_cpu(skb->protocol); u16 proto = be16_to_cpu(skb->protocol);
struct sk_buff *msg; struct sk_buff *msg;
void *hdr; void *hdr;
...@@ -16021,7 +16032,8 @@ static int __nl80211_rx_control_port(struct net_device *dev, ...@@ -16021,7 +16032,8 @@ static int __nl80211_rx_control_port(struct net_device *dev,
nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
NL80211_ATTR_PAD) || NL80211_ATTR_PAD) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, saddr) ||
nla_put(msg, NL80211_ATTR_DST_MAC, ETH_ALEN, daddr) ||
nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) || nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
(unencrypted && nla_put_flag(msg, (unencrypted && nla_put_flag(msg,
NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))) NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
......
...@@ -730,14 +730,14 @@ static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, ...@@ -730,14 +730,14 @@ static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev, 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, const u8 *src,
const bool noencrypt) __be16 proto, const bool noencrypt)
{ {
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, src, proto, noencrypt);
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); dest, src, proto, noencrypt);
trace_rdev_return_int(&rdev->wiphy, ret); trace_rdev_return_int(&rdev->wiphy, ret);
return ret; return ret;
} }
......
...@@ -1923,27 +1923,31 @@ TRACE_EVENT(rdev_mgmt_tx, ...@@ -1923,27 +1923,31 @@ 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, const u8 *src, __be16 proto,
bool unencrypted), bool unencrypted),
TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted), TP_ARGS(wiphy, netdev, buf, len, dest, src, proto, unencrypted),
TP_STRUCT__entry( TP_STRUCT__entry(
WIPHY_ENTRY WIPHY_ENTRY
NETDEV_ENTRY NETDEV_ENTRY
MAC_ENTRY(dest) MAC_ENTRY(dest)
__field(__be16, proto) MAC_ENTRY(src)
__field(u16, proto)
__field(bool, unencrypted) __field(bool, unencrypted)
), ),
TP_fast_assign( TP_fast_assign(
WIPHY_ASSIGN; WIPHY_ASSIGN;
NETDEV_ASSIGN; NETDEV_ASSIGN;
MAC_ASSIGN(dest, dest); MAC_ASSIGN(dest, dest);
__entry->proto = proto; MAC_ASSIGN(src, src);
__entry->proto = be16_to_cpu(proto);
__entry->unencrypted = unencrypted; __entry->unencrypted = unencrypted;
), ),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT "," TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", dest: " MAC_PR_FMT
" proto: 0x%x, unencrypted: %s", ", src: " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest), WIPHY_PR_ARG, NETDEV_PR_ARG,
be16_to_cpu(__entry->proto), MAC_PR_ARG(dest), MAC_PR_ARG(src),
__entry->proto,
BOOL_TO_STR(__entry->unencrypted)) BOOL_TO_STR(__entry->unencrypted))
); );
...@@ -2835,6 +2839,7 @@ TRACE_EVENT(cfg80211_rx_control_port, ...@@ -2835,6 +2839,7 @@ TRACE_EVENT(cfg80211_rx_control_port,
TP_STRUCT__entry( TP_STRUCT__entry(
NETDEV_ENTRY NETDEV_ENTRY
__field(int, len) __field(int, len)
MAC_ENTRY(to)
MAC_ENTRY(from) MAC_ENTRY(from)
__field(u16, proto) __field(u16, proto)
__field(bool, unencrypted) __field(bool, unencrypted)
...@@ -2842,12 +2847,14 @@ TRACE_EVENT(cfg80211_rx_control_port, ...@@ -2842,12 +2847,14 @@ TRACE_EVENT(cfg80211_rx_control_port,
TP_fast_assign( TP_fast_assign(
NETDEV_ASSIGN; NETDEV_ASSIGN;
__entry->len = skb->len; __entry->len = skb->len;
MAC_ASSIGN(to, eth_hdr(skb)->h_dest);
MAC_ASSIGN(from, eth_hdr(skb)->h_source); MAC_ASSIGN(from, eth_hdr(skb)->h_source);
__entry->proto = be16_to_cpu(skb->protocol); __entry->proto = be16_to_cpu(skb->protocol);
__entry->unencrypted = unencrypted; __entry->unencrypted = unencrypted;
), ),
TP_printk(NETDEV_PR_FMT ", len=%d, " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s", TP_printk(NETDEV_PR_FMT ", len=%d, dest: " MAC_PR_FMT
NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(from), ", src: " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(to), MAC_PR_ARG(from),
__entry->proto, BOOL_TO_STR(__entry->unencrypted)) __entry->proto, BOOL_TO_STR(__entry->unencrypted))
); );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment