mac80211: track AP and peer STA TDLS chan-switch support
[deliverable/linux.git] / net / mac80211 / tdls.c
CommitLineData
95224fe8
AN
1/*
2 * mac80211 TDLS handling code
3 *
4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2014, Intel Corporation
d98ad83e 6 * Copyright 2014 Intel Mobile Communications GmbH
95224fe8
AN
7 *
8 * This file is GPLv2 as found in COPYING.
9 */
10
11#include <linux/ieee80211.h>
6f7eaa47 12#include <linux/log2.h>
c887f0d3 13#include <net/cfg80211.h>
95224fe8 14#include "ieee80211_i.h"
ee10f2c7 15#include "driver-ops.h"
95224fe8 16
17e6a59a
AN
17/* give usermode some time for retries in setting up the TDLS session */
18#define TDLS_PEER_SETUP_TIMEOUT (15 * HZ)
19
20void ieee80211_tdls_peer_del_work(struct work_struct *wk)
21{
22 struct ieee80211_sub_if_data *sdata;
23 struct ieee80211_local *local;
24
25 sdata = container_of(wk, struct ieee80211_sub_if_data,
81dd2b88 26 u.mgd.tdls_peer_del_work.work);
17e6a59a
AN
27 local = sdata->local;
28
29 mutex_lock(&local->mtx);
81dd2b88
AN
30 if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer)) {
31 tdls_dbg(sdata, "TDLS del peer %pM\n", sdata->u.mgd.tdls_peer);
32 sta_info_destroy_addr(sdata, sdata->u.mgd.tdls_peer);
33 eth_zero_addr(sdata->u.mgd.tdls_peer);
17e6a59a
AN
34 }
35 mutex_unlock(&local->mtx);
36}
37
78632a17
AN
38static void ieee80211_tdls_add_ext_capab(struct ieee80211_local *local,
39 struct sk_buff *skb)
95224fe8
AN
40{
41 u8 *pos = (void *)skb_put(skb, 7);
78632a17
AN
42 bool chan_switch = local->hw.wiphy->features &
43 NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
95224fe8
AN
44
45 *pos++ = WLAN_EID_EXT_CAPABILITY;
46 *pos++ = 5; /* len */
47 *pos++ = 0x0;
48 *pos++ = 0x0;
49 *pos++ = 0x0;
78632a17 50 *pos++ = chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0;
95224fe8
AN
51 *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
52}
53
f0d29cb9
AN
54static u8
55ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
56 struct sk_buff *skb, u16 start, u16 end,
57 u16 spacing)
58{
59 u8 subband_cnt = 0, ch_cnt = 0;
60 struct ieee80211_channel *ch;
61 struct cfg80211_chan_def chandef;
62 int i, subband_start;
63
64 for (i = start; i <= end; i += spacing) {
65 if (!ch_cnt)
66 subband_start = i;
67
68 ch = ieee80211_get_channel(sdata->local->hw.wiphy, i);
69 if (ch) {
70 /* we will be active on the channel */
71 u32 flags = IEEE80211_CHAN_DISABLED |
72 IEEE80211_CHAN_NO_IR;
73 cfg80211_chandef_create(&chandef, ch,
74 NL80211_CHAN_HT20);
75 if (cfg80211_chandef_usable(sdata->local->hw.wiphy,
76 &chandef, flags)) {
77 ch_cnt++;
78 continue;
79 }
80 }
81
82 if (ch_cnt) {
83 u8 *pos = skb_put(skb, 2);
84 *pos++ = ieee80211_frequency_to_channel(subband_start);
85 *pos++ = ch_cnt;
86
87 subband_cnt++;
88 ch_cnt = 0;
89 }
90 }
91
92 return subband_cnt;
93}
94
95static void
96ieee80211_tdls_add_supp_channels(struct ieee80211_sub_if_data *sdata,
97 struct sk_buff *skb)
98{
99 /*
100 * Add possible channels for TDLS. These are channels that are allowed
101 * to be active.
102 */
103 u8 subband_cnt;
104 u8 *pos = skb_put(skb, 2);
105
106 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
107
108 /*
109 * 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as
110 * this doesn't happen in real world scenarios.
111 */
112
113 /* 2GHz, with 5MHz spacing */
114 subband_cnt = ieee80211_tdls_add_subband(sdata, skb, 2412, 2472, 5);
115
116 /* 5GHz, with 20MHz spacing */
117 subband_cnt += ieee80211_tdls_add_subband(sdata, skb, 5000, 5825, 20);
118
119 /* length */
120 *pos = 2 * subband_cnt;
121}
122
2cedd879
AN
123static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb)
124{
125 u8 *pos = (void *)skb_put(skb, 3);
126
127 *pos++ = WLAN_EID_BSS_COEX_2040;
128 *pos++ = 1; /* len */
129
130 *pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST;
131}
132
dd8c0b03
AN
133static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
134 u16 status_code)
95224fe8
AN
135{
136 struct ieee80211_local *local = sdata->local;
137 u16 capab;
138
dd8c0b03
AN
139 /* The capability will be 0 when sending a failure code */
140 if (status_code != 0)
141 return 0;
142
95224fe8
AN
143 capab = 0;
144 if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
145 return capab;
146
147 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
148 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
149 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
150 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
151
152 return capab;
153}
154
1606ef4a
AN
155static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
156 struct sk_buff *skb, const u8 *peer,
157 bool initiator)
95224fe8
AN
158{
159 struct ieee80211_tdls_lnkie *lnkid;
1606ef4a
AN
160 const u8 *init_addr, *rsp_addr;
161
162 if (initiator) {
163 init_addr = sdata->vif.addr;
164 rsp_addr = peer;
165 } else {
166 init_addr = peer;
167 rsp_addr = sdata->vif.addr;
168 }
95224fe8
AN
169
170 lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
171
172 lnkid->ie_type = WLAN_EID_LINK_ID;
173 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
174
1606ef4a
AN
175 memcpy(lnkid->bssid, sdata->u.mgd.bssid, ETH_ALEN);
176 memcpy(lnkid->init_sta, init_addr, ETH_ALEN);
177 memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN);
95224fe8
AN
178}
179
6f7eaa47
AN
180/* translate numbering in the WMM parameter IE to the mac80211 notation */
181static enum ieee80211_ac_numbers ieee80211_ac_from_wmm(int ac)
182{
183 switch (ac) {
184 default:
185 WARN_ON_ONCE(1);
186 case 0:
187 return IEEE80211_AC_BE;
188 case 1:
189 return IEEE80211_AC_BK;
190 case 2:
191 return IEEE80211_AC_VI;
192 case 3:
193 return IEEE80211_AC_VO;
194 }
195}
196
197static u8 ieee80211_wmm_aci_aifsn(int aifsn, bool acm, int aci)
198{
199 u8 ret;
200
201 ret = aifsn & 0x0f;
202 if (acm)
203 ret |= 0x10;
204 ret |= (aci << 5) & 0x60;
205 return ret;
206}
207
208static u8 ieee80211_wmm_ecw(u16 cw_min, u16 cw_max)
209{
210 return ((ilog2(cw_min + 1) << 0x0) & 0x0f) |
211 ((ilog2(cw_max + 1) << 0x4) & 0xf0);
212}
213
214static void ieee80211_tdls_add_wmm_param_ie(struct ieee80211_sub_if_data *sdata,
215 struct sk_buff *skb)
216{
217 struct ieee80211_wmm_param_ie *wmm;
218 struct ieee80211_tx_queue_params *txq;
219 int i;
220
221 wmm = (void *)skb_put(skb, sizeof(*wmm));
222 memset(wmm, 0, sizeof(*wmm));
223
224 wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
225 wmm->len = sizeof(*wmm) - 2;
226
227 wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
228 wmm->oui[1] = 0x50;
229 wmm->oui[2] = 0xf2;
230 wmm->oui_type = 2; /* WME */
231 wmm->oui_subtype = 1; /* WME param */
232 wmm->version = 1; /* WME ver */
233 wmm->qos_info = 0; /* U-APSD not in use */
234
235 /*
236 * Use the EDCA parameters defined for the BSS, or default if the AP
237 * doesn't support it, as mandated by 802.11-2012 section 10.22.4
238 */
239 for (i = 0; i < IEEE80211_NUM_ACS; i++) {
240 txq = &sdata->tx_conf[ieee80211_ac_from_wmm(i)];
241 wmm->ac[i].aci_aifsn = ieee80211_wmm_aci_aifsn(txq->aifs,
242 txq->acm, i);
243 wmm->ac[i].cw = ieee80211_wmm_ecw(txq->cw_min, txq->cw_max);
244 wmm->ac[i].txop_limit = cpu_to_le16(txq->txop);
245 }
246}
247
f09a87d2
AN
248static void
249ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
250 struct sk_buff *skb, const u8 *peer,
1606ef4a
AN
251 u8 action_code, bool initiator,
252 const u8 *extra_ies, size_t extra_ies_len)
f09a87d2
AN
253{
254 enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
40b861a0 255 struct ieee80211_local *local = sdata->local;
13cc8a4a
AN
256 struct ieee80211_supported_band *sband;
257 struct ieee80211_sta_ht_cap ht_cap;
258 struct sta_info *sta = NULL;
f09a87d2
AN
259 size_t offset = 0, noffset;
260 u8 *pos;
261
13cc8a4a
AN
262 rcu_read_lock();
263
264 /* we should have the peer STA if we're already responding */
265 if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
266 sta = sta_info_get(sdata, peer);
267 if (WARN_ON_ONCE(!sta)) {
268 rcu_read_unlock();
269 return;
270 }
271 }
272
f09a87d2
AN
273 ieee80211_add_srates_ie(sdata, skb, false, band);
274 ieee80211_add_ext_srates_ie(sdata, skb, false, band);
f0d29cb9 275 ieee80211_tdls_add_supp_channels(sdata, skb);
f09a87d2
AN
276
277 /* add any custom IEs that go before Extended Capabilities */
278 if (extra_ies_len) {
279 static const u8 before_ext_cap[] = {
280 WLAN_EID_SUPP_RATES,
281 WLAN_EID_COUNTRY,
282 WLAN_EID_EXT_SUPP_RATES,
283 WLAN_EID_SUPPORTED_CHANNELS,
284 WLAN_EID_RSN,
285 };
286 noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
287 before_ext_cap,
288 ARRAY_SIZE(before_ext_cap),
289 offset);
290 pos = skb_put(skb, noffset - offset);
291 memcpy(pos, extra_ies + offset, noffset - offset);
292 offset = noffset;
293 }
294
78632a17 295 ieee80211_tdls_add_ext_capab(local, skb);
f09a87d2 296
40b861a0
AN
297 /* add the QoS element if we support it */
298 if (local->hw.queues >= IEEE80211_NUM_ACS &&
299 action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES)
300 ieee80211_add_wmm_info_ie(skb_put(skb, 9), 0); /* no U-APSD */
301
f09a87d2
AN
302 /* add any custom IEs that go before HT capabilities */
303 if (extra_ies_len) {
304 static const u8 before_ht_cap[] = {
305 WLAN_EID_SUPP_RATES,
306 WLAN_EID_COUNTRY,
307 WLAN_EID_EXT_SUPP_RATES,
308 WLAN_EID_SUPPORTED_CHANNELS,
309 WLAN_EID_RSN,
310 WLAN_EID_EXT_CAPABILITY,
311 WLAN_EID_QOS_CAPA,
312 WLAN_EID_FAST_BSS_TRANSITION,
313 WLAN_EID_TIMEOUT_INTERVAL,
314 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
315 };
316 noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
317 before_ht_cap,
318 ARRAY_SIZE(before_ht_cap),
319 offset);
320 pos = skb_put(skb, noffset - offset);
321 memcpy(pos, extra_ies + offset, noffset - offset);
322 offset = noffset;
323 }
324
13cc8a4a
AN
325 /*
326 * with TDLS we can switch channels, and HT-caps are not necessarily
327 * the same on all bands. The specification limits the setup to a
328 * single HT-cap, so use the current band for now.
329 */
330 sband = local->hw.wiphy->bands[band];
331 memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
332 if ((action_code == WLAN_TDLS_SETUP_REQUEST ||
333 action_code == WLAN_TDLS_SETUP_RESPONSE) &&
334 ht_cap.ht_supported && (!sta || sta->sta.ht_cap.ht_supported)) {
335 if (action_code == WLAN_TDLS_SETUP_REQUEST) {
336 ieee80211_apply_htcap_overrides(sdata, &ht_cap);
337
338 /* disable SMPS in TDLS initiator */
339 ht_cap.cap |= (WLAN_HT_CAP_SM_PS_DISABLED
340 << IEEE80211_HT_CAP_SM_PS_SHIFT);
341 } else {
342 /* disable SMPS in TDLS responder */
343 sta->sta.ht_cap.cap |=
344 (WLAN_HT_CAP_SM_PS_DISABLED
345 << IEEE80211_HT_CAP_SM_PS_SHIFT);
346
347 /* the peer caps are already intersected with our own */
348 memcpy(&ht_cap, &sta->sta.ht_cap, sizeof(ht_cap));
349 }
350
351 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
352 ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap);
353 }
354
355 rcu_read_unlock();
356
2cedd879
AN
357 if (ht_cap.ht_supported &&
358 (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
359 ieee80211_tdls_add_bss_coex_ie(skb);
360
f09a87d2
AN
361 /* add any remaining IEs */
362 if (extra_ies_len) {
363 noffset = extra_ies_len;
364 pos = skb_put(skb, noffset - offset);
365 memcpy(pos, extra_ies + offset, noffset - offset);
366 }
1606ef4a
AN
367
368 ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
f09a87d2
AN
369}
370
6f7eaa47
AN
371static void
372ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
373 struct sk_buff *skb, const u8 *peer,
374 bool initiator, const u8 *extra_ies,
375 size_t extra_ies_len)
376{
377 struct ieee80211_local *local = sdata->local;
13cc8a4a 378 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
6f7eaa47 379 size_t offset = 0, noffset;
13cc8a4a 380 struct sta_info *sta, *ap_sta;
6f7eaa47
AN
381 u8 *pos;
382
383 rcu_read_lock();
384
385 sta = sta_info_get(sdata, peer);
13cc8a4a
AN
386 ap_sta = sta_info_get(sdata, ifmgd->bssid);
387 if (WARN_ON_ONCE(!sta || !ap_sta)) {
6f7eaa47
AN
388 rcu_read_unlock();
389 return;
390 }
391
392 /* add any custom IEs that go before the QoS IE */
393 if (extra_ies_len) {
394 static const u8 before_qos[] = {
395 WLAN_EID_RSN,
396 };
397 noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
398 before_qos,
399 ARRAY_SIZE(before_qos),
400 offset);
401 pos = skb_put(skb, noffset - offset);
402 memcpy(pos, extra_ies + offset, noffset - offset);
403 offset = noffset;
404 }
405
406 /* add the QoS param IE if both the peer and we support it */
a74a8c84 407 if (local->hw.queues >= IEEE80211_NUM_ACS && sta->sta.wme)
6f7eaa47
AN
408 ieee80211_tdls_add_wmm_param_ie(sdata, skb);
409
13cc8a4a
AN
410 /* add any custom IEs that go before HT operation */
411 if (extra_ies_len) {
412 static const u8 before_ht_op[] = {
413 WLAN_EID_RSN,
414 WLAN_EID_QOS_CAPA,
415 WLAN_EID_FAST_BSS_TRANSITION,
416 WLAN_EID_TIMEOUT_INTERVAL,
417 };
418 noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
419 before_ht_op,
420 ARRAY_SIZE(before_ht_op),
421 offset);
422 pos = skb_put(skb, noffset - offset);
423 memcpy(pos, extra_ies + offset, noffset - offset);
424 offset = noffset;
425 }
426
427 /* if HT support is only added in TDLS, we need an HT-operation IE */
428 if (!ap_sta->sta.ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) {
429 struct ieee80211_chanctx_conf *chanctx_conf =
430 rcu_dereference(sdata->vif.chanctx_conf);
431 if (!WARN_ON(!chanctx_conf)) {
432 pos = skb_put(skb, 2 +
433 sizeof(struct ieee80211_ht_operation));
434 /* send an empty HT operation IE */
435 ieee80211_ie_build_ht_oper(pos, &sta->sta.ht_cap,
436 &chanctx_conf->def, 0);
437 }
438 }
439
440 rcu_read_unlock();
441
6f7eaa47
AN
442 /* add any remaining IEs */
443 if (extra_ies_len) {
444 noffset = extra_ies_len;
445 pos = skb_put(skb, noffset - offset);
446 memcpy(pos, extra_ies + offset, noffset - offset);
447 }
448
449 ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
6f7eaa47
AN
450}
451
46792a2d
AN
452static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
453 struct sk_buff *skb, const u8 *peer,
1606ef4a
AN
454 u8 action_code, u16 status_code,
455 bool initiator, const u8 *extra_ies,
456 size_t extra_ies_len)
46792a2d 457{
46792a2d
AN
458 switch (action_code) {
459 case WLAN_TDLS_SETUP_REQUEST:
460 case WLAN_TDLS_SETUP_RESPONSE:
461 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
1606ef4a
AN
462 if (status_code == 0)
463 ieee80211_tdls_add_setup_start_ies(sdata, skb, peer,
464 action_code,
465 initiator,
466 extra_ies,
467 extra_ies_len);
46792a2d
AN
468 break;
469 case WLAN_TDLS_SETUP_CONFIRM:
6f7eaa47
AN
470 if (status_code == 0)
471 ieee80211_tdls_add_setup_cfm_ies(sdata, skb, peer,
472 initiator, extra_ies,
473 extra_ies_len);
474 break;
46792a2d
AN
475 case WLAN_TDLS_TEARDOWN:
476 case WLAN_TDLS_DISCOVERY_REQUEST:
f09a87d2
AN
477 if (extra_ies_len)
478 memcpy(skb_put(skb, extra_ies_len), extra_ies,
479 extra_ies_len);
1606ef4a
AN
480 if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
481 ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
46792a2d
AN
482 break;
483 }
484
46792a2d
AN
485}
486
95224fe8
AN
487static int
488ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
3b3a0162 489 const u8 *peer, u8 action_code, u8 dialog_token,
95224fe8
AN
490 u16 status_code, struct sk_buff *skb)
491{
492 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
95224fe8
AN
493 struct ieee80211_tdls_data *tf;
494
495 tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
496
497 memcpy(tf->da, peer, ETH_ALEN);
498 memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
499 tf->ether_type = cpu_to_be16(ETH_P_TDLS);
500 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
501
59cd85cb
AN
502 /* network header is after the ethernet header */
503 skb_set_network_header(skb, ETH_HLEN);
504
95224fe8
AN
505 switch (action_code) {
506 case WLAN_TDLS_SETUP_REQUEST:
507 tf->category = WLAN_CATEGORY_TDLS;
508 tf->action_code = WLAN_TDLS_SETUP_REQUEST;
509
510 skb_put(skb, sizeof(tf->u.setup_req));
511 tf->u.setup_req.dialog_token = dialog_token;
512 tf->u.setup_req.capability =
dd8c0b03
AN
513 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
514 status_code));
95224fe8
AN
515 break;
516 case WLAN_TDLS_SETUP_RESPONSE:
517 tf->category = WLAN_CATEGORY_TDLS;
518 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
519
520 skb_put(skb, sizeof(tf->u.setup_resp));
521 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
522 tf->u.setup_resp.dialog_token = dialog_token;
523 tf->u.setup_resp.capability =
dd8c0b03
AN
524 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
525 status_code));
95224fe8
AN
526 break;
527 case WLAN_TDLS_SETUP_CONFIRM:
528 tf->category = WLAN_CATEGORY_TDLS;
529 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
530
531 skb_put(skb, sizeof(tf->u.setup_cfm));
532 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
533 tf->u.setup_cfm.dialog_token = dialog_token;
534 break;
535 case WLAN_TDLS_TEARDOWN:
536 tf->category = WLAN_CATEGORY_TDLS;
537 tf->action_code = WLAN_TDLS_TEARDOWN;
538
539 skb_put(skb, sizeof(tf->u.teardown));
540 tf->u.teardown.reason_code = cpu_to_le16(status_code);
541 break;
542 case WLAN_TDLS_DISCOVERY_REQUEST:
543 tf->category = WLAN_CATEGORY_TDLS;
544 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
545
546 skb_put(skb, sizeof(tf->u.discover_req));
547 tf->u.discover_req.dialog_token = dialog_token;
548 break;
549 default:
550 return -EINVAL;
551 }
552
553 return 0;
554}
555
556static int
557ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
3b3a0162 558 const u8 *peer, u8 action_code, u8 dialog_token,
95224fe8
AN
559 u16 status_code, struct sk_buff *skb)
560{
561 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
95224fe8
AN
562 struct ieee80211_mgmt *mgmt;
563
564 mgmt = (void *)skb_put(skb, 24);
565 memset(mgmt, 0, 24);
566 memcpy(mgmt->da, peer, ETH_ALEN);
567 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
568 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
569
570 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
571 IEEE80211_STYPE_ACTION);
572
573 switch (action_code) {
574 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
575 skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
576 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
577 mgmt->u.action.u.tdls_discover_resp.action_code =
578 WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
579 mgmt->u.action.u.tdls_discover_resp.dialog_token =
580 dialog_token;
581 mgmt->u.action.u.tdls_discover_resp.capability =
dd8c0b03
AN
582 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
583 status_code));
95224fe8
AN
584 break;
585 default:
586 return -EINVAL;
587 }
588
589 return 0;
590}
591
17e6a59a
AN
592static int
593ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
594 const u8 *peer, u8 action_code,
595 u8 dialog_token, u16 status_code,
2fb6b9b8
AN
596 u32 peer_capability, bool initiator,
597 const u8 *extra_ies, size_t extra_ies_len)
95224fe8
AN
598{
599 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
600 struct ieee80211_local *local = sdata->local;
601 struct sk_buff *skb = NULL;
1277b4a9 602 u32 flags = 0;
95224fe8 603 bool send_direct;
626911cc 604 struct sta_info *sta;
95224fe8
AN
605 int ret;
606
1277b4a9
LK
607 skb = netdev_alloc_skb(dev,
608 local->hw.extra_tx_headroom +
609 max(sizeof(struct ieee80211_mgmt),
610 sizeof(struct ieee80211_tdls_data)) +
611 50 + /* supported rates */
612 7 + /* ext capab */
613 26 + /* max(WMM-info, WMM-param) */
614 2 + max(sizeof(struct ieee80211_ht_cap),
615 sizeof(struct ieee80211_ht_operation)) +
f0d29cb9 616 50 + /* supported channels */
2cedd879 617 3 + /* 40/20 BSS coex */
1277b4a9
LK
618 extra_ies_len +
619 sizeof(struct ieee80211_tdls_lnkie));
95224fe8
AN
620 if (!skb)
621 return -ENOMEM;
622
623 skb_reserve(skb, local->hw.extra_tx_headroom);
624
625 switch (action_code) {
626 case WLAN_TDLS_SETUP_REQUEST:
627 case WLAN_TDLS_SETUP_RESPONSE:
628 case WLAN_TDLS_SETUP_CONFIRM:
629 case WLAN_TDLS_TEARDOWN:
630 case WLAN_TDLS_DISCOVERY_REQUEST:
631 ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
632 action_code, dialog_token,
633 status_code, skb);
634 send_direct = false;
635 break;
636 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
637 ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
638 dialog_token, status_code,
639 skb);
640 send_direct = true;
641 break;
642 default:
643 ret = -ENOTSUPP;
644 break;
645 }
646
647 if (ret < 0)
648 goto fail;
649
626911cc
AN
650 rcu_read_lock();
651 sta = sta_info_get(sdata, peer);
652
653 /* infer the initiator if we can, to support old userspace */
95224fe8
AN
654 switch (action_code) {
655 case WLAN_TDLS_SETUP_REQUEST:
8b94148c 656 if (sta) {
626911cc 657 set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
8b94148c
AN
658 sta->sta.tdls_initiator = false;
659 }
626911cc 660 /* fall-through */
95224fe8 661 case WLAN_TDLS_SETUP_CONFIRM:
95224fe8 662 case WLAN_TDLS_DISCOVERY_REQUEST:
626911cc 663 initiator = true;
95224fe8
AN
664 break;
665 case WLAN_TDLS_SETUP_RESPONSE:
626911cc
AN
666 /*
667 * In some testing scenarios, we send a request and response.
668 * Make the last packet sent take effect for the initiator
669 * value.
670 */
8b94148c 671 if (sta) {
626911cc 672 clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
8b94148c
AN
673 sta->sta.tdls_initiator = true;
674 }
626911cc 675 /* fall-through */
95224fe8 676 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
626911cc 677 initiator = false;
2fb6b9b8
AN
678 break;
679 case WLAN_TDLS_TEARDOWN:
680 /* any value is ok */
95224fe8
AN
681 break;
682 default:
683 ret = -ENOTSUPP;
626911cc 684 break;
95224fe8
AN
685 }
686
46792a2d
AN
687 if (sta && test_sta_flag(sta, WLAN_STA_TDLS_INITIATOR))
688 initiator = true;
2fb6b9b8 689
626911cc
AN
690 rcu_read_unlock();
691 if (ret < 0)
692 goto fail;
693
1606ef4a
AN
694 ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code,
695 initiator, extra_ies, extra_ies_len);
95224fe8
AN
696 if (send_direct) {
697 ieee80211_tx_skb(sdata, skb);
698 return 0;
699 }
700
701 /*
702 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
703 * we should default to AC_VI.
704 */
705 switch (action_code) {
706 case WLAN_TDLS_SETUP_REQUEST:
707 case WLAN_TDLS_SETUP_RESPONSE:
708 skb_set_queue_mapping(skb, IEEE80211_AC_BK);
709 skb->priority = 2;
710 break;
711 default:
712 skb_set_queue_mapping(skb, IEEE80211_AC_VI);
713 skb->priority = 5;
714 break;
715 }
716
1277b4a9
LK
717 /*
718 * Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress.
719 * Later, if no ACK is returned from peer, we will re-send the teardown
720 * packet through the AP.
721 */
722 if ((action_code == WLAN_TDLS_TEARDOWN) &&
723 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
724 struct sta_info *sta = NULL;
725 bool try_resend; /* Should we keep skb for possible resend */
726
727 /* If not sending directly to peer - no point in keeping skb */
728 rcu_read_lock();
729 sta = sta_info_get(sdata, peer);
730 try_resend = sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
731 rcu_read_unlock();
732
733 spin_lock_bh(&sdata->u.mgd.teardown_lock);
734 if (try_resend && !sdata->u.mgd.teardown_skb) {
735 /* Mark it as requiring TX status callback */
736 flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
737 IEEE80211_TX_INTFL_MLME_CONN_TX;
738
739 /*
740 * skb is copied since mac80211 will later set
741 * properties that might not be the same as the AP,
742 * such as encryption, QoS, addresses, etc.
743 *
744 * No problem if skb_copy() fails, so no need to check.
745 */
746 sdata->u.mgd.teardown_skb = skb_copy(skb, GFP_ATOMIC);
747 sdata->u.mgd.orig_teardown_skb = skb;
748 }
749 spin_unlock_bh(&sdata->u.mgd.teardown_lock);
750 }
751
95224fe8
AN
752 /* disable bottom halves when entering the Tx path */
753 local_bh_disable();
1277b4a9 754 __ieee80211_subif_start_xmit(skb, dev, flags);
95224fe8
AN
755 local_bh_enable();
756
757 return ret;
758
759fail:
760 dev_kfree_skb(skb);
761 return ret;
762}
763
191dd469
AN
764static int
765ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
766 const u8 *peer, u8 action_code, u8 dialog_token,
767 u16 status_code, u32 peer_capability, bool initiator,
768 const u8 *extra_ies, size_t extra_ies_len)
17e6a59a
AN
769{
770 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
771 struct ieee80211_local *local = sdata->local;
772 int ret;
773
17e6a59a
AN
774 mutex_lock(&local->mtx);
775
776 /* we don't support concurrent TDLS peer setups */
81dd2b88
AN
777 if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer) &&
778 !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) {
17e6a59a
AN
779 ret = -EBUSY;
780 goto exit;
781 }
782
7adc3e46
AN
783 /*
784 * make sure we have a STA representing the peer so we drop or buffer
785 * non-TDLS-setup frames to the peer. We can't send other packets
6ae32e5d
AN
786 * during setup through the AP path.
787 * Allow error packets to be sent - sometimes we don't even add a STA
788 * before failing the setup.
7adc3e46 789 */
6ae32e5d
AN
790 if (status_code == 0) {
791 rcu_read_lock();
792 if (!sta_info_get(sdata, peer)) {
793 rcu_read_unlock();
794 ret = -ENOLINK;
795 goto exit;
796 }
7adc3e46 797 rcu_read_unlock();
7adc3e46 798 }
7adc3e46 799
db67d661
AN
800 ieee80211_flush_queues(local, sdata);
801
17e6a59a
AN
802 ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
803 dialog_token, status_code,
2fb6b9b8
AN
804 peer_capability, initiator,
805 extra_ies, extra_ies_len);
17e6a59a
AN
806 if (ret < 0)
807 goto exit;
808
81dd2b88 809 memcpy(sdata->u.mgd.tdls_peer, peer, ETH_ALEN);
191dd469 810 ieee80211_queue_delayed_work(&sdata->local->hw,
81dd2b88 811 &sdata->u.mgd.tdls_peer_del_work,
191dd469 812 TDLS_PEER_SETUP_TIMEOUT);
17e6a59a
AN
813
814exit:
815 mutex_unlock(&local->mtx);
191dd469
AN
816 return ret;
817}
818
db67d661
AN
819static int
820ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
821 const u8 *peer, u8 action_code, u8 dialog_token,
822 u16 status_code, u32 peer_capability,
823 bool initiator, const u8 *extra_ies,
824 size_t extra_ies_len)
825{
826 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
827 struct ieee80211_local *local = sdata->local;
828 struct sta_info *sta;
829 int ret;
830
831 /*
832 * No packets can be transmitted to the peer via the AP during setup -
833 * the STA is set as a TDLS peer, but is not authorized.
834 * During teardown, we prevent direct transmissions by stopping the
835 * queues and flushing all direct packets.
836 */
837 ieee80211_stop_vif_queues(local, sdata,
838 IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
839 ieee80211_flush_queues(local, sdata);
840
841 ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
842 dialog_token, status_code,
843 peer_capability, initiator,
844 extra_ies, extra_ies_len);
845 if (ret < 0)
846 sdata_err(sdata, "Failed sending TDLS teardown packet %d\n",
847 ret);
848
849 /*
850 * Remove the STA AUTH flag to force further traffic through the AP. If
851 * the STA was unreachable, it was already removed.
852 */
853 rcu_read_lock();
854 sta = sta_info_get(sdata, peer);
855 if (sta)
856 clear_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
857 rcu_read_unlock();
858
859 ieee80211_wake_vif_queues(local, sdata,
860 IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
861
862 return 0;
863}
864
191dd469
AN
865int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
866 const u8 *peer, u8 action_code, u8 dialog_token,
867 u16 status_code, u32 peer_capability,
868 bool initiator, const u8 *extra_ies,
869 size_t extra_ies_len)
870{
871 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
872 int ret;
873
874 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
875 return -ENOTSUPP;
876
877 /* make sure we are in managed mode, and associated */
878 if (sdata->vif.type != NL80211_IFTYPE_STATION ||
879 !sdata->u.mgd.associated)
880 return -EINVAL;
881
882 switch (action_code) {
883 case WLAN_TDLS_SETUP_REQUEST:
884 case WLAN_TDLS_SETUP_RESPONSE:
885 ret = ieee80211_tdls_mgmt_setup(wiphy, dev, peer, action_code,
886 dialog_token, status_code,
887 peer_capability, initiator,
888 extra_ies, extra_ies_len);
889 break;
890 case WLAN_TDLS_TEARDOWN:
db67d661
AN
891 ret = ieee80211_tdls_mgmt_teardown(wiphy, dev, peer,
892 action_code, dialog_token,
893 status_code,
894 peer_capability, initiator,
895 extra_ies, extra_ies_len);
896 break;
191dd469 897 case WLAN_TDLS_DISCOVERY_REQUEST:
ee10f2c7
AN
898 /*
899 * Protect the discovery so we can hear the TDLS discovery
900 * response frame. It is transmitted directly and not buffered
901 * by the AP.
902 */
903 drv_mgd_protect_tdls_discover(sdata->local, sdata);
904 /* fall-through */
905 case WLAN_TDLS_SETUP_CONFIRM:
191dd469
AN
906 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
907 /* no special handling */
908 ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
909 action_code,
910 dialog_token,
911 status_code,
912 peer_capability,
913 initiator, extra_ies,
914 extra_ies_len);
915 break;
916 default:
917 ret = -EOPNOTSUPP;
918 break;
919 }
17e6a59a
AN
920
921 tdls_dbg(sdata, "TDLS mgmt action %d peer %pM status %d\n",
922 action_code, peer, ret);
923 return ret;
924}
925
95224fe8 926int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
3b3a0162 927 const u8 *peer, enum nl80211_tdls_operation oper)
95224fe8
AN
928{
929 struct sta_info *sta;
930 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
17e6a59a
AN
931 struct ieee80211_local *local = sdata->local;
932 int ret;
95224fe8
AN
933
934 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
935 return -ENOTSUPP;
936
937 if (sdata->vif.type != NL80211_IFTYPE_STATION)
938 return -EINVAL;
939
17e6a59a
AN
940 switch (oper) {
941 case NL80211_TDLS_ENABLE_LINK:
942 case NL80211_TDLS_DISABLE_LINK:
943 break;
944 case NL80211_TDLS_TEARDOWN:
945 case NL80211_TDLS_SETUP:
946 case NL80211_TDLS_DISCOVERY_REQ:
947 /* We don't support in-driver setup/teardown/discovery */
948 return -ENOTSUPP;
949 }
950
951 mutex_lock(&local->mtx);
95224fe8
AN
952 tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
953
954 switch (oper) {
955 case NL80211_TDLS_ENABLE_LINK:
956 rcu_read_lock();
957 sta = sta_info_get(sdata, peer);
958 if (!sta) {
959 rcu_read_unlock();
17e6a59a
AN
960 ret = -ENOLINK;
961 break;
95224fe8
AN
962 }
963
964 set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
965 rcu_read_unlock();
17e6a59a 966
81dd2b88
AN
967 WARN_ON_ONCE(is_zero_ether_addr(sdata->u.mgd.tdls_peer) ||
968 !ether_addr_equal(sdata->u.mgd.tdls_peer, peer));
17e6a59a 969 ret = 0;
95224fe8
AN
970 break;
971 case NL80211_TDLS_DISABLE_LINK:
bb3f8486
LK
972 /*
973 * The teardown message in ieee80211_tdls_mgmt_teardown() was
974 * created while the queues were stopped, so it might still be
975 * pending. Before flushing the queues we need to be sure the
976 * message is handled by the tasklet handling pending messages,
977 * otherwise we might start destroying the station before
978 * sending the teardown packet.
979 * Note that this only forces the tasklet to flush pendings -
980 * not to stop the tasklet from rescheduling itself.
981 */
982 tasklet_kill(&local->tx_pending_tasklet);
db67d661
AN
983 /* flush a potentially queued teardown packet */
984 ieee80211_flush_queues(local, sdata);
985
17e6a59a
AN
986 ret = sta_info_destroy_addr(sdata, peer);
987 break;
95224fe8 988 default:
17e6a59a
AN
989 ret = -ENOTSUPP;
990 break;
95224fe8
AN
991 }
992
81dd2b88
AN
993 if (ret == 0 && ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) {
994 cancel_delayed_work(&sdata->u.mgd.tdls_peer_del_work);
995 eth_zero_addr(sdata->u.mgd.tdls_peer);
17e6a59a
AN
996 }
997
998 mutex_unlock(&local->mtx);
999 return ret;
95224fe8 1000}
c887f0d3
AN
1001
1002void ieee80211_tdls_oper_request(struct ieee80211_vif *vif, const u8 *peer,
1003 enum nl80211_tdls_operation oper,
1004 u16 reason_code, gfp_t gfp)
1005{
1006 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1007
1008 if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) {
1009 sdata_err(sdata, "Discarding TDLS oper %d - not STA or disconnected\n",
1010 oper);
1011 return;
1012 }
1013
1014 cfg80211_tdls_oper_request(sdata->dev, peer, oper, reason_code, gfp);
1015}
1016EXPORT_SYMBOL(ieee80211_tdls_oper_request);
This page took 0.136326 seconds and 5 git commands to generate.