diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/sta_info.h | 3 | ||||
-rw-r--r-- | net/mac80211/tdls.c | 35 |
2 files changed, 27 insertions, 11 deletions
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 2a04361b2162..e37f00969526 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -47,6 +47,8 @@ | |||
47 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. | 47 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. |
48 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct | 48 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct |
49 | * packets. This means the link is enabled. | 49 | * packets. This means the link is enabled. |
50 | * @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this | ||
51 | * station. | ||
50 | * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was | 52 | * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was |
51 | * keeping station in power-save mode, reply when the driver | 53 | * keeping station in power-save mode, reply when the driver |
52 | * unblocks the station. | 54 | * unblocks the station. |
@@ -76,6 +78,7 @@ enum ieee80211_sta_info_flags { | |||
76 | WLAN_STA_PSPOLL, | 78 | WLAN_STA_PSPOLL, |
77 | WLAN_STA_TDLS_PEER, | 79 | WLAN_STA_TDLS_PEER, |
78 | WLAN_STA_TDLS_PEER_AUTH, | 80 | WLAN_STA_TDLS_PEER_AUTH, |
81 | WLAN_STA_TDLS_INITIATOR, | ||
79 | WLAN_STA_UAPSD, | 82 | WLAN_STA_UAPSD, |
80 | WLAN_STA_SP, | 83 | WLAN_STA_SP, |
81 | WLAN_STA_4ADDR_EVENT, | 84 | WLAN_STA_4ADDR_EVENT, |
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index f7185338a0fa..b01b3104b445 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c | |||
@@ -203,6 +203,7 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, | |||
203 | struct sk_buff *skb = NULL; | 203 | struct sk_buff *skb = NULL; |
204 | bool send_direct; | 204 | bool send_direct; |
205 | const u8 *init_addr, *rsp_addr; | 205 | const u8 *init_addr, *rsp_addr; |
206 | struct sta_info *sta; | ||
206 | int ret; | 207 | int ret; |
207 | 208 | ||
208 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 209 | 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, | |||
245 | if (extra_ies_len) | 246 | if (extra_ies_len) |
246 | memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); | 247 | memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); |
247 | 248 | ||
248 | /* sanity check for initiator */ | 249 | rcu_read_lock(); |
250 | sta = sta_info_get(sdata, peer); | ||
251 | |||
252 | /* infer the initiator if we can, to support old userspace */ | ||
249 | switch (action_code) { | 253 | switch (action_code) { |
250 | case WLAN_TDLS_SETUP_REQUEST: | 254 | case WLAN_TDLS_SETUP_REQUEST: |
255 | if (sta) | ||
256 | set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR); | ||
257 | /* fall-through */ | ||
251 | case WLAN_TDLS_SETUP_CONFIRM: | 258 | case WLAN_TDLS_SETUP_CONFIRM: |
252 | case WLAN_TDLS_DISCOVERY_REQUEST: | 259 | case WLAN_TDLS_DISCOVERY_REQUEST: |
253 | if (!initiator) { | 260 | initiator = true; |
254 | ret = -EINVAL; | ||
255 | goto fail; | ||
256 | } | ||
257 | break; | 261 | break; |
258 | case WLAN_TDLS_SETUP_RESPONSE: | 262 | case WLAN_TDLS_SETUP_RESPONSE: |
263 | /* | ||
264 | * In some testing scenarios, we send a request and response. | ||
265 | * Make the last packet sent take effect for the initiator | ||
266 | * value. | ||
267 | */ | ||
268 | if (sta) | ||
269 | clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR); | ||
270 | /* fall-through */ | ||
259 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | 271 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: |
260 | if (initiator) { | 272 | initiator = false; |
261 | ret = -EINVAL; | ||
262 | goto fail; | ||
263 | } | ||
264 | break; | 273 | break; |
265 | case WLAN_TDLS_TEARDOWN: | 274 | case WLAN_TDLS_TEARDOWN: |
266 | /* any value is ok */ | 275 | /* any value is ok */ |
267 | break; | 276 | break; |
268 | default: | 277 | default: |
269 | ret = -ENOTSUPP; | 278 | ret = -ENOTSUPP; |
270 | goto fail; | 279 | break; |
271 | } | 280 | } |
272 | 281 | ||
273 | if (initiator) { | 282 | if (initiator || (sta && test_sta_flag(sta, WLAN_STA_TDLS_INITIATOR))) { |
274 | init_addr = sdata->vif.addr; | 283 | init_addr = sdata->vif.addr; |
275 | rsp_addr = peer; | 284 | rsp_addr = peer; |
276 | } else { | 285 | } else { |
@@ -278,6 +287,10 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, | |||
278 | rsp_addr = sdata->vif.addr; | 287 | rsp_addr = sdata->vif.addr; |
279 | } | 288 | } |
280 | 289 | ||
290 | rcu_read_unlock(); | ||
291 | if (ret < 0) | ||
292 | goto fail; | ||
293 | |||
281 | ieee80211_tdls_add_link_ie(skb, init_addr, rsp_addr, | 294 | ieee80211_tdls_add_link_ie(skb, init_addr, rsp_addr, |
282 | sdata->u.mgd.bssid); | 295 | sdata->u.mgd.bssid); |
283 | 296 | ||