2 * mac80211 TDLS handling code
4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2014, Intel Corporation
7 * This file is GPLv2 as found in COPYING.
10 #include <linux/ieee80211.h>
11 #include "ieee80211_i.h"
13 static void ieee80211_tdls_add_ext_capab(struct sk_buff
*skb
)
15 u8
*pos
= (void *)skb_put(skb
, 7);
17 *pos
++ = WLAN_EID_EXT_CAPABILITY
;
23 *pos
++ = WLAN_EXT_CAPA5_TDLS_ENABLED
;
26 static u16
ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data
*sdata
)
28 struct ieee80211_local
*local
= sdata
->local
;
32 if (ieee80211_get_sdata_band(sdata
) != IEEE80211_BAND_2GHZ
)
35 if (!(local
->hw
.flags
& IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE
))
36 capab
|= WLAN_CAPABILITY_SHORT_SLOT_TIME
;
37 if (!(local
->hw
.flags
& IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE
))
38 capab
|= WLAN_CAPABILITY_SHORT_PREAMBLE
;
43 static void ieee80211_tdls_add_link_ie(struct sk_buff
*skb
, const u8
*src_addr
,
44 const u8
*peer
, const u8
*bssid
)
46 struct ieee80211_tdls_lnkie
*lnkid
;
48 lnkid
= (void *)skb_put(skb
, sizeof(struct ieee80211_tdls_lnkie
));
50 lnkid
->ie_type
= WLAN_EID_LINK_ID
;
51 lnkid
->ie_len
= sizeof(struct ieee80211_tdls_lnkie
) - 2;
53 memcpy(lnkid
->bssid
, bssid
, ETH_ALEN
);
54 memcpy(lnkid
->init_sta
, src_addr
, ETH_ALEN
);
55 memcpy(lnkid
->resp_sta
, peer
, ETH_ALEN
);
59 ieee80211_prep_tdls_encap_data(struct wiphy
*wiphy
, struct net_device
*dev
,
60 const u8
*peer
, u8 action_code
, u8 dialog_token
,
61 u16 status_code
, struct sk_buff
*skb
)
63 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
64 enum ieee80211_band band
= ieee80211_get_sdata_band(sdata
);
65 struct ieee80211_tdls_data
*tf
;
67 tf
= (void *)skb_put(skb
, offsetof(struct ieee80211_tdls_data
, u
));
69 memcpy(tf
->da
, peer
, ETH_ALEN
);
70 memcpy(tf
->sa
, sdata
->vif
.addr
, ETH_ALEN
);
71 tf
->ether_type
= cpu_to_be16(ETH_P_TDLS
);
72 tf
->payload_type
= WLAN_TDLS_SNAP_RFTYPE
;
74 switch (action_code
) {
75 case WLAN_TDLS_SETUP_REQUEST
:
76 tf
->category
= WLAN_CATEGORY_TDLS
;
77 tf
->action_code
= WLAN_TDLS_SETUP_REQUEST
;
79 skb_put(skb
, sizeof(tf
->u
.setup_req
));
80 tf
->u
.setup_req
.dialog_token
= dialog_token
;
81 tf
->u
.setup_req
.capability
=
82 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata
));
84 ieee80211_add_srates_ie(sdata
, skb
, false, band
);
85 ieee80211_add_ext_srates_ie(sdata
, skb
, false, band
);
86 ieee80211_tdls_add_ext_capab(skb
);
88 case WLAN_TDLS_SETUP_RESPONSE
:
89 tf
->category
= WLAN_CATEGORY_TDLS
;
90 tf
->action_code
= WLAN_TDLS_SETUP_RESPONSE
;
92 skb_put(skb
, sizeof(tf
->u
.setup_resp
));
93 tf
->u
.setup_resp
.status_code
= cpu_to_le16(status_code
);
94 tf
->u
.setup_resp
.dialog_token
= dialog_token
;
95 tf
->u
.setup_resp
.capability
=
96 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata
));
98 ieee80211_add_srates_ie(sdata
, skb
, false, band
);
99 ieee80211_add_ext_srates_ie(sdata
, skb
, false, band
);
100 ieee80211_tdls_add_ext_capab(skb
);
102 case WLAN_TDLS_SETUP_CONFIRM
:
103 tf
->category
= WLAN_CATEGORY_TDLS
;
104 tf
->action_code
= WLAN_TDLS_SETUP_CONFIRM
;
106 skb_put(skb
, sizeof(tf
->u
.setup_cfm
));
107 tf
->u
.setup_cfm
.status_code
= cpu_to_le16(status_code
);
108 tf
->u
.setup_cfm
.dialog_token
= dialog_token
;
110 case WLAN_TDLS_TEARDOWN
:
111 tf
->category
= WLAN_CATEGORY_TDLS
;
112 tf
->action_code
= WLAN_TDLS_TEARDOWN
;
114 skb_put(skb
, sizeof(tf
->u
.teardown
));
115 tf
->u
.teardown
.reason_code
= cpu_to_le16(status_code
);
117 case WLAN_TDLS_DISCOVERY_REQUEST
:
118 tf
->category
= WLAN_CATEGORY_TDLS
;
119 tf
->action_code
= WLAN_TDLS_DISCOVERY_REQUEST
;
121 skb_put(skb
, sizeof(tf
->u
.discover_req
));
122 tf
->u
.discover_req
.dialog_token
= dialog_token
;
132 ieee80211_prep_tdls_direct(struct wiphy
*wiphy
, struct net_device
*dev
,
133 const u8
*peer
, u8 action_code
, u8 dialog_token
,
134 u16 status_code
, struct sk_buff
*skb
)
136 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
137 enum ieee80211_band band
= ieee80211_get_sdata_band(sdata
);
138 struct ieee80211_mgmt
*mgmt
;
140 mgmt
= (void *)skb_put(skb
, 24);
142 memcpy(mgmt
->da
, peer
, ETH_ALEN
);
143 memcpy(mgmt
->sa
, sdata
->vif
.addr
, ETH_ALEN
);
144 memcpy(mgmt
->bssid
, sdata
->u
.mgd
.bssid
, ETH_ALEN
);
146 mgmt
->frame_control
= cpu_to_le16(IEEE80211_FTYPE_MGMT
|
147 IEEE80211_STYPE_ACTION
);
149 switch (action_code
) {
150 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES
:
151 skb_put(skb
, 1 + sizeof(mgmt
->u
.action
.u
.tdls_discover_resp
));
152 mgmt
->u
.action
.category
= WLAN_CATEGORY_PUBLIC
;
153 mgmt
->u
.action
.u
.tdls_discover_resp
.action_code
=
154 WLAN_PUB_ACTION_TDLS_DISCOVER_RES
;
155 mgmt
->u
.action
.u
.tdls_discover_resp
.dialog_token
=
157 mgmt
->u
.action
.u
.tdls_discover_resp
.capability
=
158 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata
));
160 ieee80211_add_srates_ie(sdata
, skb
, false, band
);
161 ieee80211_add_ext_srates_ie(sdata
, skb
, false, band
);
162 ieee80211_tdls_add_ext_capab(skb
);
171 int ieee80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
172 const u8
*peer
, u8 action_code
, u8 dialog_token
,
173 u16 status_code
, u32 peer_capability
,
174 const u8
*extra_ies
, size_t extra_ies_len
)
176 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
177 struct ieee80211_local
*local
= sdata
->local
;
178 struct sk_buff
*skb
= NULL
;
182 if (!(wiphy
->flags
& WIPHY_FLAG_SUPPORTS_TDLS
))
185 /* make sure we are in managed mode, and associated */
186 if (sdata
->vif
.type
!= NL80211_IFTYPE_STATION
||
187 !sdata
->u
.mgd
.associated
)
190 tdls_dbg(sdata
, "TDLS mgmt action %d peer %pM\n",
193 skb
= dev_alloc_skb(local
->hw
.extra_tx_headroom
+
194 max(sizeof(struct ieee80211_mgmt
),
195 sizeof(struct ieee80211_tdls_data
)) +
196 50 + /* supported rates */
199 sizeof(struct ieee80211_tdls_lnkie
));
203 skb_reserve(skb
, local
->hw
.extra_tx_headroom
);
205 switch (action_code
) {
206 case WLAN_TDLS_SETUP_REQUEST
:
207 case WLAN_TDLS_SETUP_RESPONSE
:
208 case WLAN_TDLS_SETUP_CONFIRM
:
209 case WLAN_TDLS_TEARDOWN
:
210 case WLAN_TDLS_DISCOVERY_REQUEST
:
211 ret
= ieee80211_prep_tdls_encap_data(wiphy
, dev
, peer
,
212 action_code
, dialog_token
,
216 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES
:
217 ret
= ieee80211_prep_tdls_direct(wiphy
, dev
, peer
, action_code
,
218 dialog_token
, status_code
,
231 memcpy(skb_put(skb
, extra_ies_len
), extra_ies
, extra_ies_len
);
233 /* the TDLS link IE is always added last */
234 switch (action_code
) {
235 case WLAN_TDLS_SETUP_REQUEST
:
236 case WLAN_TDLS_SETUP_CONFIRM
:
237 case WLAN_TDLS_TEARDOWN
:
238 case WLAN_TDLS_DISCOVERY_REQUEST
:
239 /* we are the initiator */
240 ieee80211_tdls_add_link_ie(skb
, sdata
->vif
.addr
, peer
,
243 case WLAN_TDLS_SETUP_RESPONSE
:
244 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES
:
245 /* we are the responder */
246 ieee80211_tdls_add_link_ie(skb
, peer
, sdata
->vif
.addr
,
255 ieee80211_tx_skb(sdata
, skb
);
260 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
261 * we should default to AC_VI.
263 switch (action_code
) {
264 case WLAN_TDLS_SETUP_REQUEST
:
265 case WLAN_TDLS_SETUP_RESPONSE
:
266 skb_set_queue_mapping(skb
, IEEE80211_AC_BK
);
270 skb_set_queue_mapping(skb
, IEEE80211_AC_VI
);
275 /* disable bottom halves when entering the Tx path */
277 ret
= ieee80211_subif_start_xmit(skb
, dev
);
287 int ieee80211_tdls_oper(struct wiphy
*wiphy
, struct net_device
*dev
,
288 const u8
*peer
, enum nl80211_tdls_operation oper
)
290 struct sta_info
*sta
;
291 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
293 if (!(wiphy
->flags
& WIPHY_FLAG_SUPPORTS_TDLS
))
296 if (sdata
->vif
.type
!= NL80211_IFTYPE_STATION
)
299 tdls_dbg(sdata
, "TDLS oper %d peer %pM\n", oper
, peer
);
302 case NL80211_TDLS_ENABLE_LINK
:
304 sta
= sta_info_get(sdata
, peer
);
310 set_sta_flag(sta
, WLAN_STA_TDLS_PEER_AUTH
);
313 case NL80211_TDLS_DISABLE_LINK
:
314 return sta_info_destroy_addr(sdata
, peer
);
315 case NL80211_TDLS_TEARDOWN
:
316 case NL80211_TDLS_SETUP
:
317 case NL80211_TDLS_DISCOVERY_REQ
:
318 /* We don't support in-driver setup/teardown/discovery */