aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tdls.c
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2014-07-17 10:14:17 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-07-21 06:14:03 -0400
commit626911cc60d873b38f7ca4c5c537fcb918c658d7 (patch)
tree957d99d21d0caf75a60c51897a4636db27c7a6c7 /net/mac80211/tdls.c
parent1d4cc30c86301543a09ff4118a36044546c7cfa1 (diff)
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>
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