]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/mac80211/tdls.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
[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 <net/cfg80211.h>
12 #include "ieee80211_i.h"
13 #include "driver-ops.h"
14
15 /* give usermode some time for retries in setting up the TDLS session */
16 #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ)
17
18 void ieee80211_tdls_peer_del_work(struct work_struct *wk)
19 {
20         struct ieee80211_sub_if_data *sdata;
21         struct ieee80211_local *local;
22
23         sdata = container_of(wk, struct ieee80211_sub_if_data,
24                              tdls_peer_del_work.work);
25         local = sdata->local;
26
27         mutex_lock(&local->mtx);
28         if (!is_zero_ether_addr(sdata->tdls_peer)) {
29                 tdls_dbg(sdata, "TDLS del peer %pM\n", sdata->tdls_peer);
30                 sta_info_destroy_addr(sdata, sdata->tdls_peer);
31                 eth_zero_addr(sdata->tdls_peer);
32         }
33         mutex_unlock(&local->mtx);
34 }
35
36 static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
37 {
38         u8 *pos = (void *)skb_put(skb, 7);
39
40         *pos++ = WLAN_EID_EXT_CAPABILITY;
41         *pos++ = 5; /* len */
42         *pos++ = 0x0;
43         *pos++ = 0x0;
44         *pos++ = 0x0;
45         *pos++ = 0x0;
46         *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
47 }
48
49 static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
50 {
51         struct ieee80211_local *local = sdata->local;
52         u16 capab;
53
54         capab = 0;
55         if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
56                 return capab;
57
58         if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
59                 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
60         if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
61                 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
62
63         return capab;
64 }
65
66 static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
67                                        const u8 *peer, const u8 *bssid)
68 {
69         struct ieee80211_tdls_lnkie *lnkid;
70
71         lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
72
73         lnkid->ie_type = WLAN_EID_LINK_ID;
74         lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
75
76         memcpy(lnkid->bssid, bssid, ETH_ALEN);
77         memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
78         memcpy(lnkid->resp_sta, peer, ETH_ALEN);
79 }
80
81 static int
82 ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
83                                const u8 *peer, u8 action_code, u8 dialog_token,
84                                u16 status_code, struct sk_buff *skb)
85 {
86         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
87         enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
88         struct ieee80211_tdls_data *tf;
89
90         tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
91
92         memcpy(tf->da, peer, ETH_ALEN);
93         memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
94         tf->ether_type = cpu_to_be16(ETH_P_TDLS);
95         tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
96
97         switch (action_code) {
98         case WLAN_TDLS_SETUP_REQUEST:
99                 tf->category = WLAN_CATEGORY_TDLS;
100                 tf->action_code = WLAN_TDLS_SETUP_REQUEST;
101
102                 skb_put(skb, sizeof(tf->u.setup_req));
103                 tf->u.setup_req.dialog_token = dialog_token;
104                 tf->u.setup_req.capability =
105                         cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
106
107                 ieee80211_add_srates_ie(sdata, skb, false, band);
108                 ieee80211_add_ext_srates_ie(sdata, skb, false, band);
109                 ieee80211_tdls_add_ext_capab(skb);
110                 break;
111         case WLAN_TDLS_SETUP_RESPONSE:
112                 tf->category = WLAN_CATEGORY_TDLS;
113                 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
114
115                 skb_put(skb, sizeof(tf->u.setup_resp));
116                 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
117                 tf->u.setup_resp.dialog_token = dialog_token;
118                 tf->u.setup_resp.capability =
119                         cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
120
121                 ieee80211_add_srates_ie(sdata, skb, false, band);
122                 ieee80211_add_ext_srates_ie(sdata, skb, false, band);
123                 ieee80211_tdls_add_ext_capab(skb);
124                 break;
125         case WLAN_TDLS_SETUP_CONFIRM:
126                 tf->category = WLAN_CATEGORY_TDLS;
127                 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
128
129                 skb_put(skb, sizeof(tf->u.setup_cfm));
130                 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
131                 tf->u.setup_cfm.dialog_token = dialog_token;
132                 break;
133         case WLAN_TDLS_TEARDOWN:
134                 tf->category = WLAN_CATEGORY_TDLS;
135                 tf->action_code = WLAN_TDLS_TEARDOWN;
136
137                 skb_put(skb, sizeof(tf->u.teardown));
138                 tf->u.teardown.reason_code = cpu_to_le16(status_code);
139                 break;
140         case WLAN_TDLS_DISCOVERY_REQUEST:
141                 tf->category = WLAN_CATEGORY_TDLS;
142                 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
143
144                 skb_put(skb, sizeof(tf->u.discover_req));
145                 tf->u.discover_req.dialog_token = dialog_token;
146                 break;
147         default:
148                 return -EINVAL;
149         }
150
151         return 0;
152 }
153
154 static int
155 ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
156                            const u8 *peer, u8 action_code, u8 dialog_token,
157                            u16 status_code, struct sk_buff *skb)
158 {
159         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
160         enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
161         struct ieee80211_mgmt *mgmt;
162
163         mgmt = (void *)skb_put(skb, 24);
164         memset(mgmt, 0, 24);
165         memcpy(mgmt->da, peer, ETH_ALEN);
166         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
167         memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
168
169         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
170                                           IEEE80211_STYPE_ACTION);
171
172         switch (action_code) {
173         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
174                 skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
175                 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
176                 mgmt->u.action.u.tdls_discover_resp.action_code =
177                         WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
178                 mgmt->u.action.u.tdls_discover_resp.dialog_token =
179                         dialog_token;
180                 mgmt->u.action.u.tdls_discover_resp.capability =
181                         cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
182
183                 ieee80211_add_srates_ie(sdata, skb, false, band);
184                 ieee80211_add_ext_srates_ie(sdata, skb, false, band);
185                 ieee80211_tdls_add_ext_capab(skb);
186                 break;
187         default:
188                 return -EINVAL;
189         }
190
191         return 0;
192 }
193
194 static int
195 ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
196                                 const u8 *peer, u8 action_code,
197                                 u8 dialog_token, u16 status_code,
198                                 u32 peer_capability, bool initiator,
199                                 const u8 *extra_ies, size_t extra_ies_len)
200 {
201         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
202         struct ieee80211_local *local = sdata->local;
203         struct sk_buff *skb = NULL;
204         bool send_direct;
205         const u8 *init_addr, *rsp_addr;
206         int ret;
207
208         skb = dev_alloc_skb(local->hw.extra_tx_headroom +
209                             max(sizeof(struct ieee80211_mgmt),
210                                 sizeof(struct ieee80211_tdls_data)) +
211                             50 + /* supported rates */
212                             7 + /* ext capab */
213                             extra_ies_len +
214                             sizeof(struct ieee80211_tdls_lnkie));
215         if (!skb)
216                 return -ENOMEM;
217
218         skb_reserve(skb, local->hw.extra_tx_headroom);
219
220         switch (action_code) {
221         case WLAN_TDLS_SETUP_REQUEST:
222         case WLAN_TDLS_SETUP_RESPONSE:
223         case WLAN_TDLS_SETUP_CONFIRM:
224         case WLAN_TDLS_TEARDOWN:
225         case WLAN_TDLS_DISCOVERY_REQUEST:
226                 ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
227                                                      action_code, dialog_token,
228                                                      status_code, skb);
229                 send_direct = false;
230                 break;
231         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
232                 ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
233                                                  dialog_token, status_code,
234                                                  skb);
235                 send_direct = true;
236                 break;
237         default:
238                 ret = -ENOTSUPP;
239                 break;
240         }
241
242         if (ret < 0)
243                 goto fail;
244
245         if (extra_ies_len)
246                 memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
247
248         /* sanity check for initiator */
249         switch (action_code) {
250         case WLAN_TDLS_SETUP_REQUEST:
251         case WLAN_TDLS_SETUP_CONFIRM:
252         case WLAN_TDLS_DISCOVERY_REQUEST:
253                 if (!initiator) {
254                         ret = -EINVAL;
255                         goto fail;
256                 }
257                 break;
258         case WLAN_TDLS_SETUP_RESPONSE:
259         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
260                 if (initiator) {
261                         ret = -EINVAL;
262                         goto fail;
263                 }
264                 break;
265         case WLAN_TDLS_TEARDOWN:
266                 /* any value is ok */
267                 break;
268         default:
269                 ret = -ENOTSUPP;
270                 goto fail;
271         }
272
273         if (initiator) {
274                 init_addr = sdata->vif.addr;
275                 rsp_addr = peer;
276         } else {
277                 init_addr = peer;
278                 rsp_addr = sdata->vif.addr;
279         }
280
281         ieee80211_tdls_add_link_ie(skb, init_addr, rsp_addr,
282                                    sdata->u.mgd.bssid);
283
284         if (send_direct) {
285                 ieee80211_tx_skb(sdata, skb);
286                 return 0;
287         }
288
289         /*
290          * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
291          * we should default to AC_VI.
292          */
293         switch (action_code) {
294         case WLAN_TDLS_SETUP_REQUEST:
295         case WLAN_TDLS_SETUP_RESPONSE:
296                 skb_set_queue_mapping(skb, IEEE80211_AC_BK);
297                 skb->priority = 2;
298                 break;
299         default:
300                 skb_set_queue_mapping(skb, IEEE80211_AC_VI);
301                 skb->priority = 5;
302                 break;
303         }
304
305         /* disable bottom halves when entering the Tx path */
306         local_bh_disable();
307         ret = ieee80211_subif_start_xmit(skb, dev);
308         local_bh_enable();
309
310         return ret;
311
312 fail:
313         dev_kfree_skb(skb);
314         return ret;
315 }
316
317 static int
318 ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
319                           const u8 *peer, u8 action_code, u8 dialog_token,
320                           u16 status_code, u32 peer_capability, bool initiator,
321                           const u8 *extra_ies, size_t extra_ies_len)
322 {
323         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
324         struct ieee80211_local *local = sdata->local;
325         int ret;
326
327         mutex_lock(&local->mtx);
328
329         /* we don't support concurrent TDLS peer setups */
330         if (!is_zero_ether_addr(sdata->tdls_peer) &&
331             !ether_addr_equal(sdata->tdls_peer, peer)) {
332                 ret = -EBUSY;
333                 goto exit;
334         }
335
336         /*
337          * make sure we have a STA representing the peer so we drop or buffer
338          * non-TDLS-setup frames to the peer. We can't send other packets
339          * during setup through the AP path
340          */
341         rcu_read_lock();
342         if (!sta_info_get(sdata, peer)) {
343                 rcu_read_unlock();
344                 ret = -ENOLINK;
345                 goto exit;
346         }
347         rcu_read_unlock();
348
349         ieee80211_flush_queues(local, sdata);
350
351         ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
352                                               dialog_token, status_code,
353                                               peer_capability, initiator,
354                                               extra_ies, extra_ies_len);
355         if (ret < 0)
356                 goto exit;
357
358         memcpy(sdata->tdls_peer, peer, ETH_ALEN);
359         ieee80211_queue_delayed_work(&sdata->local->hw,
360                                      &sdata->tdls_peer_del_work,
361                                      TDLS_PEER_SETUP_TIMEOUT);
362
363 exit:
364         mutex_unlock(&local->mtx);
365         return ret;
366 }
367
368 static int
369 ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
370                              const u8 *peer, u8 action_code, u8 dialog_token,
371                              u16 status_code, u32 peer_capability,
372                              bool initiator, const u8 *extra_ies,
373                              size_t extra_ies_len)
374 {
375         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
376         struct ieee80211_local *local = sdata->local;
377         struct sta_info *sta;
378         int ret;
379
380         /*
381          * No packets can be transmitted to the peer via the AP during setup -
382          * the STA is set as a TDLS peer, but is not authorized.
383          * During teardown, we prevent direct transmissions by stopping the
384          * queues and flushing all direct packets.
385          */
386         ieee80211_stop_vif_queues(local, sdata,
387                                   IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
388         ieee80211_flush_queues(local, sdata);
389
390         ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
391                                               dialog_token, status_code,
392                                               peer_capability, initiator,
393                                               extra_ies, extra_ies_len);
394         if (ret < 0)
395                 sdata_err(sdata, "Failed sending TDLS teardown packet %d\n",
396                           ret);
397
398         /*
399          * Remove the STA AUTH flag to force further traffic through the AP. If
400          * the STA was unreachable, it was already removed.
401          */
402         rcu_read_lock();
403         sta = sta_info_get(sdata, peer);
404         if (sta)
405                 clear_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
406         rcu_read_unlock();
407
408         ieee80211_wake_vif_queues(local, sdata,
409                                   IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
410
411         return 0;
412 }
413
414 int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
415                         const u8 *peer, u8 action_code, u8 dialog_token,
416                         u16 status_code, u32 peer_capability,
417                         bool initiator, const u8 *extra_ies,
418                         size_t extra_ies_len)
419 {
420         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
421         int ret;
422
423         if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
424                 return -ENOTSUPP;
425
426         /* make sure we are in managed mode, and associated */
427         if (sdata->vif.type != NL80211_IFTYPE_STATION ||
428             !sdata->u.mgd.associated)
429                 return -EINVAL;
430
431         switch (action_code) {
432         case WLAN_TDLS_SETUP_REQUEST:
433         case WLAN_TDLS_SETUP_RESPONSE:
434                 ret = ieee80211_tdls_mgmt_setup(wiphy, dev, peer, action_code,
435                                                 dialog_token, status_code,
436                                                 peer_capability, initiator,
437                                                 extra_ies, extra_ies_len);
438                 break;
439         case WLAN_TDLS_TEARDOWN:
440                 ret = ieee80211_tdls_mgmt_teardown(wiphy, dev, peer,
441                                                    action_code, dialog_token,
442                                                    status_code,
443                                                    peer_capability, initiator,
444                                                    extra_ies, extra_ies_len);
445                 break;
446         case WLAN_TDLS_DISCOVERY_REQUEST:
447                 /*
448                  * Protect the discovery so we can hear the TDLS discovery
449                  * response frame. It is transmitted directly and not buffered
450                  * by the AP.
451                  */
452                 drv_mgd_protect_tdls_discover(sdata->local, sdata);
453                 /* fall-through */
454         case WLAN_TDLS_SETUP_CONFIRM:
455         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
456                 /* no special handling */
457                 ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
458                                                       action_code,
459                                                       dialog_token,
460                                                       status_code,
461                                                       peer_capability,
462                                                       initiator, extra_ies,
463                                                       extra_ies_len);
464                 break;
465         default:
466                 ret = -EOPNOTSUPP;
467                 break;
468         }
469
470         tdls_dbg(sdata, "TDLS mgmt action %d peer %pM status %d\n",
471                  action_code, peer, ret);
472         return ret;
473 }
474
475 int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
476                         const u8 *peer, enum nl80211_tdls_operation oper)
477 {
478         struct sta_info *sta;
479         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
480         struct ieee80211_local *local = sdata->local;
481         int ret;
482
483         if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
484                 return -ENOTSUPP;
485
486         if (sdata->vif.type != NL80211_IFTYPE_STATION)
487                 return -EINVAL;
488
489         switch (oper) {
490         case NL80211_TDLS_ENABLE_LINK:
491         case NL80211_TDLS_DISABLE_LINK:
492                 break;
493         case NL80211_TDLS_TEARDOWN:
494         case NL80211_TDLS_SETUP:
495         case NL80211_TDLS_DISCOVERY_REQ:
496                 /* We don't support in-driver setup/teardown/discovery */
497                 return -ENOTSUPP;
498         }
499
500         mutex_lock(&local->mtx);
501         tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
502
503         switch (oper) {
504         case NL80211_TDLS_ENABLE_LINK:
505                 rcu_read_lock();
506                 sta = sta_info_get(sdata, peer);
507                 if (!sta) {
508                         rcu_read_unlock();
509                         ret = -ENOLINK;
510                         break;
511                 }
512
513                 set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
514                 rcu_read_unlock();
515
516                 WARN_ON_ONCE(is_zero_ether_addr(sdata->tdls_peer) ||
517                              !ether_addr_equal(sdata->tdls_peer, peer));
518                 ret = 0;
519                 break;
520         case NL80211_TDLS_DISABLE_LINK:
521                 /* flush a potentially queued teardown packet */
522                 ieee80211_flush_queues(local, sdata);
523
524                 ret = sta_info_destroy_addr(sdata, peer);
525                 break;
526         default:
527                 ret = -ENOTSUPP;
528                 break;
529         }
530
531         if (ret == 0 && ether_addr_equal(sdata->tdls_peer, peer)) {
532                 cancel_delayed_work(&sdata->tdls_peer_del_work);
533                 eth_zero_addr(sdata->tdls_peer);
534         }
535
536         mutex_unlock(&local->mtx);
537         return ret;
538 }
539
540 void ieee80211_tdls_oper_request(struct ieee80211_vif *vif, const u8 *peer,
541                                  enum nl80211_tdls_operation oper,
542                                  u16 reason_code, gfp_t gfp)
543 {
544         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
545
546         if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) {
547                 sdata_err(sdata, "Discarding TDLS oper %d - not STA or disconnected\n",
548                           oper);
549                 return;
550         }
551
552         cfg80211_tdls_oper_request(sdata->dev, peer, oper, reason_code, gfp);
553 }
554 EXPORT_SYMBOL(ieee80211_tdls_oper_request);