]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/mac80211/tdls.c
mac80211: move TDLS data to mgd private part
[karo-tx-linux.git] / net / mac80211 / tdls.c
1 /*
2  * mac80211 TDLS handling code
3  *
4  * Copyright 2006-2010  Johannes Berg <johannes@sipsolutions.net>
5  * Copyright 2014, Intel Corporation
6  *
7  * This file is GPLv2 as found in COPYING.
8  */
9
10 #include <linux/ieee80211.h>
11 #include <linux/log2.h>
12 #include <net/cfg80211.h>
13 #include "ieee80211_i.h"
14 #include "driver-ops.h"
15
16 /* give usermode some time for retries in setting up the TDLS session */
17 #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ)
18
19 void ieee80211_tdls_peer_del_work(struct work_struct *wk)
20 {
21         struct ieee80211_sub_if_data *sdata;
22         struct ieee80211_local *local;
23
24         sdata = container_of(wk, struct ieee80211_sub_if_data,
25                              u.mgd.tdls_peer_del_work.work);
26         local = sdata->local;
27
28         mutex_lock(&local->mtx);
29         if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer)) {
30                 tdls_dbg(sdata, "TDLS del peer %pM\n", sdata->u.mgd.tdls_peer);
31                 sta_info_destroy_addr(sdata, sdata->u.mgd.tdls_peer);
32                 eth_zero_addr(sdata->u.mgd.tdls_peer);
33         }
34         mutex_unlock(&local->mtx);
35 }
36
37 static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
38 {
39         u8 *pos = (void *)skb_put(skb, 7);
40
41         *pos++ = WLAN_EID_EXT_CAPABILITY;
42         *pos++ = 5; /* len */
43         *pos++ = 0x0;
44         *pos++ = 0x0;
45         *pos++ = 0x0;
46         *pos++ = 0x0;
47         *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
48 }
49
50 static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
51                                         u16 status_code)
52 {
53         struct ieee80211_local *local = sdata->local;
54         u16 capab;
55
56         /* The capability will be 0 when sending a failure code */
57         if (status_code != 0)
58                 return 0;
59
60         capab = 0;
61         if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
62                 return capab;
63
64         if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
65                 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
66         if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
67                 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
68
69         return capab;
70 }
71
72 static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
73                                        struct sk_buff *skb, const u8 *peer,
74                                        bool initiator)
75 {
76         struct ieee80211_tdls_lnkie *lnkid;
77         const u8 *init_addr, *rsp_addr;
78
79         if (initiator) {
80                 init_addr = sdata->vif.addr;
81                 rsp_addr = peer;
82         } else {
83                 init_addr = peer;
84                 rsp_addr = sdata->vif.addr;
85         }
86
87         lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
88
89         lnkid->ie_type = WLAN_EID_LINK_ID;
90         lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
91
92         memcpy(lnkid->bssid, sdata->u.mgd.bssid, ETH_ALEN);
93         memcpy(lnkid->init_sta, init_addr, ETH_ALEN);
94         memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN);
95 }
96
97 /* translate numbering in the WMM parameter IE to the mac80211 notation */
98 static enum ieee80211_ac_numbers ieee80211_ac_from_wmm(int ac)
99 {
100         switch (ac) {
101         default:
102                 WARN_ON_ONCE(1);
103         case 0:
104                 return IEEE80211_AC_BE;
105         case 1:
106                 return IEEE80211_AC_BK;
107         case 2:
108                 return IEEE80211_AC_VI;
109         case 3:
110                 return IEEE80211_AC_VO;
111         }
112 }
113
114 static u8 ieee80211_wmm_aci_aifsn(int aifsn, bool acm, int aci)
115 {
116         u8 ret;
117
118         ret = aifsn & 0x0f;
119         if (acm)
120                 ret |= 0x10;
121         ret |= (aci << 5) & 0x60;
122         return ret;
123 }
124
125 static u8 ieee80211_wmm_ecw(u16 cw_min, u16 cw_max)
126 {
127         return ((ilog2(cw_min + 1) << 0x0) & 0x0f) |
128                ((ilog2(cw_max + 1) << 0x4) & 0xf0);
129 }
130
131 static void ieee80211_tdls_add_wmm_param_ie(struct ieee80211_sub_if_data *sdata,
132                                             struct sk_buff *skb)
133 {
134         struct ieee80211_wmm_param_ie *wmm;
135         struct ieee80211_tx_queue_params *txq;
136         int i;
137
138         wmm = (void *)skb_put(skb, sizeof(*wmm));
139         memset(wmm, 0, sizeof(*wmm));
140
141         wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
142         wmm->len = sizeof(*wmm) - 2;
143
144         wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
145         wmm->oui[1] = 0x50;
146         wmm->oui[2] = 0xf2;
147         wmm->oui_type = 2; /* WME */
148         wmm->oui_subtype = 1; /* WME param */
149         wmm->version = 1; /* WME ver */
150         wmm->qos_info = 0; /* U-APSD not in use */
151
152         /*
153          * Use the EDCA parameters defined for the BSS, or default if the AP
154          * doesn't support it, as mandated by 802.11-2012 section 10.22.4
155          */
156         for (i = 0; i < IEEE80211_NUM_ACS; i++) {
157                 txq = &sdata->tx_conf[ieee80211_ac_from_wmm(i)];
158                 wmm->ac[i].aci_aifsn = ieee80211_wmm_aci_aifsn(txq->aifs,
159                                                                txq->acm, i);
160                 wmm->ac[i].cw = ieee80211_wmm_ecw(txq->cw_min, txq->cw_max);
161                 wmm->ac[i].txop_limit = cpu_to_le16(txq->txop);
162         }
163 }
164
165 static void
166 ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
167                                    struct sk_buff *skb, const u8 *peer,
168                                    u8 action_code, bool initiator,
169                                    const u8 *extra_ies, size_t extra_ies_len)
170 {
171         enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
172         struct ieee80211_local *local = sdata->local;
173         size_t offset = 0, noffset;
174         u8 *pos;
175
176         ieee80211_add_srates_ie(sdata, skb, false, band);
177         ieee80211_add_ext_srates_ie(sdata, skb, false, band);
178
179         /* add any custom IEs that go before Extended Capabilities */
180         if (extra_ies_len) {
181                 static const u8 before_ext_cap[] = {
182                         WLAN_EID_SUPP_RATES,
183                         WLAN_EID_COUNTRY,
184                         WLAN_EID_EXT_SUPP_RATES,
185                         WLAN_EID_SUPPORTED_CHANNELS,
186                         WLAN_EID_RSN,
187                 };
188                 noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
189                                              before_ext_cap,
190                                              ARRAY_SIZE(before_ext_cap),
191                                              offset);
192                 pos = skb_put(skb, noffset - offset);
193                 memcpy(pos, extra_ies + offset, noffset - offset);
194                 offset = noffset;
195         }
196
197         ieee80211_tdls_add_ext_capab(skb);
198
199         /* add the QoS element if we support it */
200         if (local->hw.queues >= IEEE80211_NUM_ACS &&
201             action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES)
202                 ieee80211_add_wmm_info_ie(skb_put(skb, 9), 0); /* no U-APSD */
203
204         /* add any custom IEs that go before HT capabilities */
205         if (extra_ies_len) {
206                 static const u8 before_ht_cap[] = {
207                         WLAN_EID_SUPP_RATES,
208                         WLAN_EID_COUNTRY,
209                         WLAN_EID_EXT_SUPP_RATES,
210                         WLAN_EID_SUPPORTED_CHANNELS,
211                         WLAN_EID_RSN,
212                         WLAN_EID_EXT_CAPABILITY,
213                         WLAN_EID_QOS_CAPA,
214                         WLAN_EID_FAST_BSS_TRANSITION,
215                         WLAN_EID_TIMEOUT_INTERVAL,
216                         WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
217                 };
218                 noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
219                                              before_ht_cap,
220                                              ARRAY_SIZE(before_ht_cap),
221                                              offset);
222                 pos = skb_put(skb, noffset - offset);
223                 memcpy(pos, extra_ies + offset, noffset - offset);
224                 offset = noffset;
225         }
226
227         /* add any remaining IEs */
228         if (extra_ies_len) {
229                 noffset = extra_ies_len;
230                 pos = skb_put(skb, noffset - offset);
231                 memcpy(pos, extra_ies + offset, noffset - offset);
232         }
233
234         ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
235 }
236
237 static void
238 ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
239                                  struct sk_buff *skb, const u8 *peer,
240                                  bool initiator, const u8 *extra_ies,
241                                  size_t extra_ies_len)
242 {
243         struct ieee80211_local *local = sdata->local;
244         size_t offset = 0, noffset;
245         struct sta_info *sta;
246         u8 *pos;
247
248         rcu_read_lock();
249
250         sta = sta_info_get(sdata, peer);
251         if (WARN_ON_ONCE(!sta)) {
252                 rcu_read_unlock();
253                 return;
254         }
255
256         /* add any custom IEs that go before the QoS IE */
257         if (extra_ies_len) {
258                 static const u8 before_qos[] = {
259                         WLAN_EID_RSN,
260                 };
261                 noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
262                                              before_qos,
263                                              ARRAY_SIZE(before_qos),
264                                              offset);
265                 pos = skb_put(skb, noffset - offset);
266                 memcpy(pos, extra_ies + offset, noffset - offset);
267                 offset = noffset;
268         }
269
270         /* add the QoS param IE if both the peer and we support it */
271         if (local->hw.queues >= IEEE80211_NUM_ACS &&
272             test_sta_flag(sta, WLAN_STA_WME))
273                 ieee80211_tdls_add_wmm_param_ie(sdata, skb);
274
275         /* add any remaining IEs */
276         if (extra_ies_len) {
277                 noffset = extra_ies_len;
278                 pos = skb_put(skb, noffset - offset);
279                 memcpy(pos, extra_ies + offset, noffset - offset);
280         }
281
282         ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
283
284         rcu_read_unlock();
285 }
286
287 static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
288                                    struct sk_buff *skb, const u8 *peer,
289                                    u8 action_code, u16 status_code,
290                                    bool initiator, const u8 *extra_ies,
291                                    size_t extra_ies_len)
292 {
293         switch (action_code) {
294         case WLAN_TDLS_SETUP_REQUEST:
295         case WLAN_TDLS_SETUP_RESPONSE:
296         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
297                 if (status_code == 0)
298                         ieee80211_tdls_add_setup_start_ies(sdata, skb, peer,
299                                                            action_code,
300                                                            initiator,
301                                                            extra_ies,
302                                                            extra_ies_len);
303                 break;
304         case WLAN_TDLS_SETUP_CONFIRM:
305                 if (status_code == 0)
306                         ieee80211_tdls_add_setup_cfm_ies(sdata, skb, peer,
307                                                          initiator, extra_ies,
308                                                          extra_ies_len);
309                 break;
310         case WLAN_TDLS_TEARDOWN:
311         case WLAN_TDLS_DISCOVERY_REQUEST:
312                 if (extra_ies_len)
313                         memcpy(skb_put(skb, extra_ies_len), extra_ies,
314                                extra_ies_len);
315                 if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
316                         ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
317                 break;
318         }
319
320 }
321
322 static int
323 ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
324                                const u8 *peer, u8 action_code, u8 dialog_token,
325                                u16 status_code, struct sk_buff *skb)
326 {
327         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
328         struct ieee80211_tdls_data *tf;
329
330         tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
331
332         memcpy(tf->da, peer, ETH_ALEN);
333         memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
334         tf->ether_type = cpu_to_be16(ETH_P_TDLS);
335         tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
336
337         switch (action_code) {
338         case WLAN_TDLS_SETUP_REQUEST:
339                 tf->category = WLAN_CATEGORY_TDLS;
340                 tf->action_code = WLAN_TDLS_SETUP_REQUEST;
341
342                 skb_put(skb, sizeof(tf->u.setup_req));
343                 tf->u.setup_req.dialog_token = dialog_token;
344                 tf->u.setup_req.capability =
345                         cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
346                                                                  status_code));
347                 break;
348         case WLAN_TDLS_SETUP_RESPONSE:
349                 tf->category = WLAN_CATEGORY_TDLS;
350                 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
351
352                 skb_put(skb, sizeof(tf->u.setup_resp));
353                 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
354                 tf->u.setup_resp.dialog_token = dialog_token;
355                 tf->u.setup_resp.capability =
356                         cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
357                                                                  status_code));
358                 break;
359         case WLAN_TDLS_SETUP_CONFIRM:
360                 tf->category = WLAN_CATEGORY_TDLS;
361                 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
362
363                 skb_put(skb, sizeof(tf->u.setup_cfm));
364                 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
365                 tf->u.setup_cfm.dialog_token = dialog_token;
366                 break;
367         case WLAN_TDLS_TEARDOWN:
368                 tf->category = WLAN_CATEGORY_TDLS;
369                 tf->action_code = WLAN_TDLS_TEARDOWN;
370
371                 skb_put(skb, sizeof(tf->u.teardown));
372                 tf->u.teardown.reason_code = cpu_to_le16(status_code);
373                 break;
374         case WLAN_TDLS_DISCOVERY_REQUEST:
375                 tf->category = WLAN_CATEGORY_TDLS;
376                 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
377
378                 skb_put(skb, sizeof(tf->u.discover_req));
379                 tf->u.discover_req.dialog_token = dialog_token;
380                 break;
381         default:
382                 return -EINVAL;
383         }
384
385         return 0;
386 }
387
388 static int
389 ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
390                            const u8 *peer, u8 action_code, u8 dialog_token,
391                            u16 status_code, struct sk_buff *skb)
392 {
393         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
394         struct ieee80211_mgmt *mgmt;
395
396         mgmt = (void *)skb_put(skb, 24);
397         memset(mgmt, 0, 24);
398         memcpy(mgmt->da, peer, ETH_ALEN);
399         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
400         memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
401
402         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
403                                           IEEE80211_STYPE_ACTION);
404
405         switch (action_code) {
406         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
407                 skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
408                 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
409                 mgmt->u.action.u.tdls_discover_resp.action_code =
410                         WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
411                 mgmt->u.action.u.tdls_discover_resp.dialog_token =
412                         dialog_token;
413                 mgmt->u.action.u.tdls_discover_resp.capability =
414                         cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
415                                                                  status_code));
416                 break;
417         default:
418                 return -EINVAL;
419         }
420
421         return 0;
422 }
423
424 static int
425 ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
426                                 const u8 *peer, u8 action_code,
427                                 u8 dialog_token, u16 status_code,
428                                 u32 peer_capability, bool initiator,
429                                 const u8 *extra_ies, size_t extra_ies_len)
430 {
431         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
432         struct ieee80211_local *local = sdata->local;
433         struct sk_buff *skb = NULL;
434         bool send_direct;
435         struct sta_info *sta;
436         int ret;
437
438         skb = dev_alloc_skb(local->hw.extra_tx_headroom +
439                             max(sizeof(struct ieee80211_mgmt),
440                                 sizeof(struct ieee80211_tdls_data)) +
441                             50 + /* supported rates */
442                             7 + /* ext capab */
443                             26 + /* max(WMM-info, WMM-param) */
444                             extra_ies_len +
445                             sizeof(struct ieee80211_tdls_lnkie));
446         if (!skb)
447                 return -ENOMEM;
448
449         skb_reserve(skb, local->hw.extra_tx_headroom);
450
451         switch (action_code) {
452         case WLAN_TDLS_SETUP_REQUEST:
453         case WLAN_TDLS_SETUP_RESPONSE:
454         case WLAN_TDLS_SETUP_CONFIRM:
455         case WLAN_TDLS_TEARDOWN:
456         case WLAN_TDLS_DISCOVERY_REQUEST:
457                 ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
458                                                      action_code, dialog_token,
459                                                      status_code, skb);
460                 send_direct = false;
461                 break;
462         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
463                 ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
464                                                  dialog_token, status_code,
465                                                  skb);
466                 send_direct = true;
467                 break;
468         default:
469                 ret = -ENOTSUPP;
470                 break;
471         }
472
473         if (ret < 0)
474                 goto fail;
475
476         rcu_read_lock();
477         sta = sta_info_get(sdata, peer);
478
479         /* infer the initiator if we can, to support old userspace */
480         switch (action_code) {
481         case WLAN_TDLS_SETUP_REQUEST:
482                 if (sta)
483                         set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
484                 /* fall-through */
485         case WLAN_TDLS_SETUP_CONFIRM:
486         case WLAN_TDLS_DISCOVERY_REQUEST:
487                 initiator = true;
488                 break;
489         case WLAN_TDLS_SETUP_RESPONSE:
490                 /*
491                  * In some testing scenarios, we send a request and response.
492                  * Make the last packet sent take effect for the initiator
493                  * value.
494                  */
495                 if (sta)
496                         clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
497                 /* fall-through */
498         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
499                 initiator = false;
500                 break;
501         case WLAN_TDLS_TEARDOWN:
502                 /* any value is ok */
503                 break;
504         default:
505                 ret = -ENOTSUPP;
506                 break;
507         }
508
509         if (sta && test_sta_flag(sta, WLAN_STA_TDLS_INITIATOR))
510                 initiator = true;
511
512         rcu_read_unlock();
513         if (ret < 0)
514                 goto fail;
515
516         ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code,
517                                initiator, extra_ies, extra_ies_len);
518         if (send_direct) {
519                 ieee80211_tx_skb(sdata, skb);
520                 return 0;
521         }
522
523         /*
524          * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
525          * we should default to AC_VI.
526          */
527         switch (action_code) {
528         case WLAN_TDLS_SETUP_REQUEST:
529         case WLAN_TDLS_SETUP_RESPONSE:
530                 skb_set_queue_mapping(skb, IEEE80211_AC_BK);
531                 skb->priority = 2;
532                 break;
533         default:
534                 skb_set_queue_mapping(skb, IEEE80211_AC_VI);
535                 skb->priority = 5;
536                 break;
537         }
538
539         /* disable bottom halves when entering the Tx path */
540         local_bh_disable();
541         ret = ieee80211_subif_start_xmit(skb, dev);
542         local_bh_enable();
543
544         return ret;
545
546 fail:
547         dev_kfree_skb(skb);
548         return ret;
549 }
550
551 static int
552 ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
553                           const u8 *peer, u8 action_code, u8 dialog_token,
554                           u16 status_code, u32 peer_capability, bool initiator,
555                           const u8 *extra_ies, size_t extra_ies_len)
556 {
557         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
558         struct ieee80211_local *local = sdata->local;
559         int ret;
560
561         mutex_lock(&local->mtx);
562
563         /* we don't support concurrent TDLS peer setups */
564         if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer) &&
565             !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) {
566                 ret = -EBUSY;
567                 goto exit;
568         }
569
570         /*
571          * make sure we have a STA representing the peer so we drop or buffer
572          * non-TDLS-setup frames to the peer. We can't send other packets
573          * during setup through the AP path.
574          * Allow error packets to be sent - sometimes we don't even add a STA
575          * before failing the setup.
576          */
577         if (status_code == 0) {
578                 rcu_read_lock();
579                 if (!sta_info_get(sdata, peer)) {
580                         rcu_read_unlock();
581                         ret = -ENOLINK;
582                         goto exit;
583                 }
584                 rcu_read_unlock();
585         }
586
587         ieee80211_flush_queues(local, sdata);
588
589         ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
590                                               dialog_token, status_code,
591                                               peer_capability, initiator,
592                                               extra_ies, extra_ies_len);
593         if (ret < 0)
594                 goto exit;
595
596         memcpy(sdata->u.mgd.tdls_peer, peer, ETH_ALEN);
597         ieee80211_queue_delayed_work(&sdata->local->hw,
598                                      &sdata->u.mgd.tdls_peer_del_work,
599                                      TDLS_PEER_SETUP_TIMEOUT);
600
601 exit:
602         mutex_unlock(&local->mtx);
603         return ret;
604 }
605
606 static int
607 ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
608                              const u8 *peer, u8 action_code, u8 dialog_token,
609                              u16 status_code, u32 peer_capability,
610                              bool initiator, const u8 *extra_ies,
611                              size_t extra_ies_len)
612 {
613         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
614         struct ieee80211_local *local = sdata->local;
615         struct sta_info *sta;
616         int ret;
617
618         /*
619          * No packets can be transmitted to the peer via the AP during setup -
620          * the STA is set as a TDLS peer, but is not authorized.
621          * During teardown, we prevent direct transmissions by stopping the
622          * queues and flushing all direct packets.
623          */
624         ieee80211_stop_vif_queues(local, sdata,
625                                   IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
626         ieee80211_flush_queues(local, sdata);
627
628         ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
629                                               dialog_token, status_code,
630                                               peer_capability, initiator,
631                                               extra_ies, extra_ies_len);
632         if (ret < 0)
633                 sdata_err(sdata, "Failed sending TDLS teardown packet %d\n",
634                           ret);
635
636         /*
637          * Remove the STA AUTH flag to force further traffic through the AP. If
638          * the STA was unreachable, it was already removed.
639          */
640         rcu_read_lock();
641         sta = sta_info_get(sdata, peer);
642         if (sta)
643                 clear_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
644         rcu_read_unlock();
645
646         ieee80211_wake_vif_queues(local, sdata,
647                                   IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
648
649         return 0;
650 }
651
652 int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
653                         const u8 *peer, u8 action_code, u8 dialog_token,
654                         u16 status_code, u32 peer_capability,
655                         bool initiator, const u8 *extra_ies,
656                         size_t extra_ies_len)
657 {
658         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
659         int ret;
660
661         if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
662                 return -ENOTSUPP;
663
664         /* make sure we are in managed mode, and associated */
665         if (sdata->vif.type != NL80211_IFTYPE_STATION ||
666             !sdata->u.mgd.associated)
667                 return -EINVAL;
668
669         switch (action_code) {
670         case WLAN_TDLS_SETUP_REQUEST:
671         case WLAN_TDLS_SETUP_RESPONSE:
672                 ret = ieee80211_tdls_mgmt_setup(wiphy, dev, peer, action_code,
673                                                 dialog_token, status_code,
674                                                 peer_capability, initiator,
675                                                 extra_ies, extra_ies_len);
676                 break;
677         case WLAN_TDLS_TEARDOWN:
678                 ret = ieee80211_tdls_mgmt_teardown(wiphy, dev, peer,
679                                                    action_code, dialog_token,
680                                                    status_code,
681                                                    peer_capability, initiator,
682                                                    extra_ies, extra_ies_len);
683                 break;
684         case WLAN_TDLS_DISCOVERY_REQUEST:
685                 /*
686                  * Protect the discovery so we can hear the TDLS discovery
687                  * response frame. It is transmitted directly and not buffered
688                  * by the AP.
689                  */
690                 drv_mgd_protect_tdls_discover(sdata->local, sdata);
691                 /* fall-through */
692         case WLAN_TDLS_SETUP_CONFIRM:
693         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
694                 /* no special handling */
695                 ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
696                                                       action_code,
697                                                       dialog_token,
698                                                       status_code,
699                                                       peer_capability,
700                                                       initiator, extra_ies,
701                                                       extra_ies_len);
702                 break;
703         default:
704                 ret = -EOPNOTSUPP;
705                 break;
706         }
707
708         tdls_dbg(sdata, "TDLS mgmt action %d peer %pM status %d\n",
709                  action_code, peer, ret);
710         return ret;
711 }
712
713 int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
714                         const u8 *peer, enum nl80211_tdls_operation oper)
715 {
716         struct sta_info *sta;
717         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
718         struct ieee80211_local *local = sdata->local;
719         int ret;
720
721         if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
722                 return -ENOTSUPP;
723
724         if (sdata->vif.type != NL80211_IFTYPE_STATION)
725                 return -EINVAL;
726
727         switch (oper) {
728         case NL80211_TDLS_ENABLE_LINK:
729         case NL80211_TDLS_DISABLE_LINK:
730                 break;
731         case NL80211_TDLS_TEARDOWN:
732         case NL80211_TDLS_SETUP:
733         case NL80211_TDLS_DISCOVERY_REQ:
734                 /* We don't support in-driver setup/teardown/discovery */
735                 return -ENOTSUPP;
736         }
737
738         mutex_lock(&local->mtx);
739         tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
740
741         switch (oper) {
742         case NL80211_TDLS_ENABLE_LINK:
743                 rcu_read_lock();
744                 sta = sta_info_get(sdata, peer);
745                 if (!sta) {
746                         rcu_read_unlock();
747                         ret = -ENOLINK;
748                         break;
749                 }
750
751                 set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
752                 rcu_read_unlock();
753
754                 WARN_ON_ONCE(is_zero_ether_addr(sdata->u.mgd.tdls_peer) ||
755                              !ether_addr_equal(sdata->u.mgd.tdls_peer, peer));
756                 ret = 0;
757                 break;
758         case NL80211_TDLS_DISABLE_LINK:
759                 /* flush a potentially queued teardown packet */
760                 ieee80211_flush_queues(local, sdata);
761
762                 ret = sta_info_destroy_addr(sdata, peer);
763                 break;
764         default:
765                 ret = -ENOTSUPP;
766                 break;
767         }
768
769         if (ret == 0 && ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) {
770                 cancel_delayed_work(&sdata->u.mgd.tdls_peer_del_work);
771                 eth_zero_addr(sdata->u.mgd.tdls_peer);
772         }
773
774         mutex_unlock(&local->mtx);
775         return ret;
776 }
777
778 void ieee80211_tdls_oper_request(struct ieee80211_vif *vif, const u8 *peer,
779                                  enum nl80211_tdls_operation oper,
780                                  u16 reason_code, gfp_t gfp)
781 {
782         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
783
784         if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) {
785                 sdata_err(sdata, "Discarding TDLS oper %d - not STA or disconnected\n",
786                           oper);
787                 return;
788         }
789
790         cfg80211_tdls_oper_request(sdata->dev, peer, oper, reason_code, gfp);
791 }
792 EXPORT_SYMBOL(ieee80211_tdls_oper_request);