aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tdls.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/tdls.c')
-rw-r--r--net/mac80211/tdls.c35
1 files changed, 24 insertions, 11 deletions
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