summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorMarkus Theil <markus.theil@tu-ilmenau.de>2020-01-15 15:55:22 +0300
committerJohannes Berg <johannes.berg@intel.com>2020-02-07 14:58:37 +0300
commit8c3ed7aa2b9ef666195b789e9b02e28383243fa8 (patch)
tree271a9d36a6af297b55b5fb4ecaa08b92db413546 /net
parentc0058df73309906ef4d5383fbaa10c43ebddc48a (diff)
downloadlinux-8c3ed7aa2b9ef666195b789e9b02e28383243fa8.tar.xz
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: Markus 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: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/tx.c3
-rw-r--r--net/wireless/nl80211.c18
-rw-r--r--net/wireless/rdev-ops.h8
-rw-r--r--net/wireless/trace.h27
5 files changed, 40 insertions, 19 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8a49d78ad7c9..da9eaa9ee37e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -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);
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
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,
const u8 *buf, size_t len);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4296d9d71311..059c66b6bb5c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -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,
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_local *local = sdata->local;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4c0ea54e0f59..33fe6ac1c242 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -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_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_SRC_MAC] = NLA_POLICY_ETH_ADDR,
+ [NL80211_ATTR_DST_MAC] = NLA_POLICY_ETH_ADDR,
};
/* policy for the key attributes */
@@ -13694,6 +13696,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
const u8 *buf;
size_t len;
u8 *dest;
+ u8 src[ETH_ALEN];
u16 proto;
bool noencrypt;
int err;
@@ -13731,6 +13734,13 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
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);
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)
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
return rdev_tx_control_port(rdev, dev, buf, len,
- dest, cpu_to_be16(proto), noencrypt);
+ dest, src, cpu_to_be16(proto), noencrypt);
out:
wdev_unlock(wdev);
@@ -15996,7 +16006,8 @@ static int __nl80211_rx_control_port(struct net_device *dev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
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);
struct sk_buff *msg;
void *hdr;
@@ -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_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
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) ||
(unencrypted && nla_put_flag(msg,
NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index e853a4fe6f97..39e6c1db3092 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -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,
struct net_device *dev,
const void *buf, size_t len,
- const u8 *dest, __be16 proto,
- const bool noencrypt)
+ const u8 *dest, const u8 *src,
+ __be16 proto, const bool noencrypt)
{
int ret;
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,
- dest, proto, noencrypt);
+ dest, src, proto, noencrypt);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index d98ad2b3143b..fefa255fd062 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1923,27 +1923,31 @@ TRACE_EVENT(rdev_mgmt_tx,
TRACE_EVENT(rdev_tx_control_port,
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),
- TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted),
+ TP_ARGS(wiphy, netdev, buf, len, dest, src, proto, unencrypted),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
MAC_ENTRY(dest)
- __field(__be16, proto)
+ MAC_ENTRY(src)
+ __field(u16, proto)
__field(bool, unencrypted)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
MAC_ASSIGN(dest, dest);
- __entry->proto = proto;
+ MAC_ASSIGN(src, src);
+ __entry->proto = be16_to_cpu(proto);
__entry->unencrypted = unencrypted;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ","
- " proto: 0x%x, unencrypted: %s",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest),
- be16_to_cpu(__entry->proto),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", dest: " MAC_PR_FMT
+ ", src: " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
+ WIPHY_PR_ARG, NETDEV_PR_ARG,
+ MAC_PR_ARG(dest), MAC_PR_ARG(src),
+ __entry->proto,
BOOL_TO_STR(__entry->unencrypted))
);
@@ -2835,6 +2839,7 @@ TRACE_EVENT(cfg80211_rx_control_port,
TP_STRUCT__entry(
NETDEV_ENTRY
__field(int, len)
+ MAC_ENTRY(to)
MAC_ENTRY(from)
__field(u16, proto)
__field(bool, unencrypted)
@@ -2842,12 +2847,14 @@ TRACE_EVENT(cfg80211_rx_control_port,
TP_fast_assign(
NETDEV_ASSIGN;
__entry->len = skb->len;
+ MAC_ASSIGN(to, eth_hdr(skb)->h_dest);
MAC_ASSIGN(from, eth_hdr(skb)->h_source);
__entry->proto = be16_to_cpu(skb->protocol);
__entry->unencrypted = unencrypted;
),
- TP_printk(NETDEV_PR_FMT ", len=%d, " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
- NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(from),
+ TP_printk(NETDEV_PR_FMT ", len=%d, dest: " MAC_PR_FMT
+ ", 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))
);