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 "ieee80211_i.h" 12 13 static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) 14 { 15 u8 *pos = (void *)skb_put(skb, 7); 16 17 *pos++ = WLAN_EID_EXT_CAPABILITY; 18 *pos++ = 5; /* len */ 19 *pos++ = 0x0; 20 *pos++ = 0x0; 21 *pos++ = 0x0; 22 *pos++ = 0x0; 23 *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; 24 } 25 26 static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) 27 { 28 struct ieee80211_local *local = sdata->local; 29 u16 capab; 30 31 capab = 0; 32 if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) 33 return capab; 34 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; 39 40 return capab; 41 } 42 43 static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, 44 const u8 *peer, const u8 *bssid) 45 { 46 struct ieee80211_tdls_lnkie *lnkid; 47 48 lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); 49 50 lnkid->ie_type = WLAN_EID_LINK_ID; 51 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; 52 53 memcpy(lnkid->bssid, bssid, ETH_ALEN); 54 memcpy(lnkid->init_sta, src_addr, ETH_ALEN); 55 memcpy(lnkid->resp_sta, peer, ETH_ALEN); 56 } 57 58 static int 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) 62 { 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; 66 67 tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); 68 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; 73 74 switch (action_code) { 75 case WLAN_TDLS_SETUP_REQUEST: 76 tf->category = WLAN_CATEGORY_TDLS; 77 tf->action_code = WLAN_TDLS_SETUP_REQUEST; 78 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)); 83 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); 87 break; 88 case WLAN_TDLS_SETUP_RESPONSE: 89 tf->category = WLAN_CATEGORY_TDLS; 90 tf->action_code = WLAN_TDLS_SETUP_RESPONSE; 91 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)); 97 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); 101 break; 102 case WLAN_TDLS_SETUP_CONFIRM: 103 tf->category = WLAN_CATEGORY_TDLS; 104 tf->action_code = WLAN_TDLS_SETUP_CONFIRM; 105 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; 109 break; 110 case WLAN_TDLS_TEARDOWN: 111 tf->category = WLAN_CATEGORY_TDLS; 112 tf->action_code = WLAN_TDLS_TEARDOWN; 113 114 skb_put(skb, sizeof(tf->u.teardown)); 115 tf->u.teardown.reason_code = cpu_to_le16(status_code); 116 break; 117 case WLAN_TDLS_DISCOVERY_REQUEST: 118 tf->category = WLAN_CATEGORY_TDLS; 119 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; 120 121 skb_put(skb, sizeof(tf->u.discover_req)); 122 tf->u.discover_req.dialog_token = dialog_token; 123 break; 124 default: 125 return -EINVAL; 126 } 127 128 return 0; 129 } 130 131 static int 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) 135 { 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; 139 140 mgmt = (void *)skb_put(skb, 24); 141 memset(mgmt, 0, 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); 145 146 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 147 IEEE80211_STYPE_ACTION); 148 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 = 156 dialog_token; 157 mgmt->u.action.u.tdls_discover_resp.capability = 158 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); 159 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); 163 break; 164 default: 165 return -EINVAL; 166 } 167 168 return 0; 169 } 170 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) 175 { 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; 179 bool send_direct; 180 int ret; 181 182 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) 183 return -ENOTSUPP; 184 185 /* make sure we are in managed mode, and associated */ 186 if (sdata->vif.type != NL80211_IFTYPE_STATION || 187 !sdata->u.mgd.associated) 188 return -EINVAL; 189 190 tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", 191 action_code, peer); 192 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 */ 197 7 + /* ext capab */ 198 extra_ies_len + 199 sizeof(struct ieee80211_tdls_lnkie)); 200 if (!skb) 201 return -ENOMEM; 202 203 skb_reserve(skb, local->hw.extra_tx_headroom); 204 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, 213 status_code, skb); 214 send_direct = false; 215 break; 216 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: 217 ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, 218 dialog_token, status_code, 219 skb); 220 send_direct = true; 221 break; 222 default: 223 ret = -ENOTSUPP; 224 break; 225 } 226 227 if (ret < 0) 228 goto fail; 229 230 if (extra_ies_len) 231 memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); 232 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, 241 sdata->u.mgd.bssid); 242 break; 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, 247 sdata->u.mgd.bssid); 248 break; 249 default: 250 ret = -ENOTSUPP; 251 goto fail; 252 } 253 254 if (send_direct) { 255 ieee80211_tx_skb(sdata, skb); 256 return 0; 257 } 258 259 /* 260 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise 261 * we should default to AC_VI. 262 */ 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); 267 skb->priority = 2; 268 break; 269 default: 270 skb_set_queue_mapping(skb, IEEE80211_AC_VI); 271 skb->priority = 5; 272 break; 273 } 274 275 /* disable bottom halves when entering the Tx path */ 276 local_bh_disable(); 277 ret = ieee80211_subif_start_xmit(skb, dev); 278 local_bh_enable(); 279 280 return ret; 281 282 fail: 283 dev_kfree_skb(skb); 284 return ret; 285 } 286 287 int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, 288 const u8 *peer, enum nl80211_tdls_operation oper) 289 { 290 struct sta_info *sta; 291 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 292 293 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) 294 return -ENOTSUPP; 295 296 if (sdata->vif.type != NL80211_IFTYPE_STATION) 297 return -EINVAL; 298 299 tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); 300 301 switch (oper) { 302 case NL80211_TDLS_ENABLE_LINK: 303 rcu_read_lock(); 304 sta = sta_info_get(sdata, peer); 305 if (!sta) { 306 rcu_read_unlock(); 307 return -ENOLINK; 308 } 309 310 set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); 311 rcu_read_unlock(); 312 break; 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 */ 319 return -ENOTSUPP; 320 default: 321 return -ENOTSUPP; 322 } 323 324 return 0; 325 } 326