mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 18:30:06 +00:00
mac80211: track TDLS initiator internally
Infer the TDLS initiator and track it in mac80211 via a STA flag. This avoids breaking old userspace that doesn't pass it via nl80211 APIs. The only case where userspace will need to pass the initiator is when the STA is removed due to unreachability before a teardown packet is sent. Support for unreachability was only recently added to wpa_supplicant, so it won't be a problem in practice. Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
1d4cc30c86
commit
626911cc60
2 changed files with 27 additions and 11 deletions
|
@ -47,6 +47,8 @@
|
||||||
* @WLAN_STA_TDLS_PEER: Station is a TDLS peer.
|
* @WLAN_STA_TDLS_PEER: Station is a TDLS peer.
|
||||||
* @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct
|
* @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct
|
||||||
* packets. This means the link is enabled.
|
* packets. This means the link is enabled.
|
||||||
|
* @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this
|
||||||
|
* station.
|
||||||
* @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was
|
* @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was
|
||||||
* keeping station in power-save mode, reply when the driver
|
* keeping station in power-save mode, reply when the driver
|
||||||
* unblocks the station.
|
* unblocks the station.
|
||||||
|
@ -76,6 +78,7 @@ enum ieee80211_sta_info_flags {
|
||||||
WLAN_STA_PSPOLL,
|
WLAN_STA_PSPOLL,
|
||||||
WLAN_STA_TDLS_PEER,
|
WLAN_STA_TDLS_PEER,
|
||||||
WLAN_STA_TDLS_PEER_AUTH,
|
WLAN_STA_TDLS_PEER_AUTH,
|
||||||
|
WLAN_STA_TDLS_INITIATOR,
|
||||||
WLAN_STA_UAPSD,
|
WLAN_STA_UAPSD,
|
||||||
WLAN_STA_SP,
|
WLAN_STA_SP,
|
||||||
WLAN_STA_4ADDR_EVENT,
|
WLAN_STA_4ADDR_EVENT,
|
||||||
|
|
|
@ -203,6 +203,7 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
|
||||||
struct sk_buff *skb = NULL;
|
struct sk_buff *skb = NULL;
|
||||||
bool send_direct;
|
bool send_direct;
|
||||||
const u8 *init_addr, *rsp_addr;
|
const u8 *init_addr, *rsp_addr;
|
||||||
|
struct sta_info *sta;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
|
||||||
|
@ -245,32 +246,40 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
|
||||||
if (extra_ies_len)
|
if (extra_ies_len)
|
||||||
memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
|
memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
|
||||||
|
|
||||||
/* sanity check for initiator */
|
rcu_read_lock();
|
||||||
|
sta = sta_info_get(sdata, peer);
|
||||||
|
|
||||||
|
/* infer the initiator if we can, to support old userspace */
|
||||||
switch (action_code) {
|
switch (action_code) {
|
||||||
case WLAN_TDLS_SETUP_REQUEST:
|
case WLAN_TDLS_SETUP_REQUEST:
|
||||||
|
if (sta)
|
||||||
|
set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
|
||||||
|
/* fall-through */
|
||||||
case WLAN_TDLS_SETUP_CONFIRM:
|
case WLAN_TDLS_SETUP_CONFIRM:
|
||||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||||
if (!initiator) {
|
initiator = true;
|
||||||
ret = -EINVAL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case WLAN_TDLS_SETUP_RESPONSE:
|
case WLAN_TDLS_SETUP_RESPONSE:
|
||||||
|
/*
|
||||||
|
* In some testing scenarios, we send a request and response.
|
||||||
|
* Make the last packet sent take effect for the initiator
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
if (sta)
|
||||||
|
clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
|
||||||
|
/* fall-through */
|
||||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||||
if (initiator) {
|
initiator = false;
|
||||||
ret = -EINVAL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case WLAN_TDLS_TEARDOWN:
|
case WLAN_TDLS_TEARDOWN:
|
||||||
/* any value is ok */
|
/* any value is ok */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -ENOTSUPP;
|
ret = -ENOTSUPP;
|
||||||
goto fail;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initiator) {
|
if (initiator || (sta && test_sta_flag(sta, WLAN_STA_TDLS_INITIATOR))) {
|
||||||
init_addr = sdata->vif.addr;
|
init_addr = sdata->vif.addr;
|
||||||
rsp_addr = peer;
|
rsp_addr = peer;
|
||||||
} else {
|
} else {
|
||||||
|
@ -278,6 +287,10 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
|
||||||
rsp_addr = sdata->vif.addr;
|
rsp_addr = sdata->vif.addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
ieee80211_tdls_add_link_ie(skb, init_addr, rsp_addr,
|
ieee80211_tdls_add_link_ie(skb, init_addr, rsp_addr,
|
||||||
sdata->u.mgd.bssid);
|
sdata->u.mgd.bssid);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue