tdls.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. #include <linux/ieee80211.h>
  10. #include "ieee80211_i.h"
  11. static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
  12. {
  13. u8 *pos = (void *)skb_put(skb, 7);
  14. *pos++ = WLAN_EID_EXT_CAPABILITY;
  15. *pos++ = 5; /* len */
  16. *pos++ = 0x0;
  17. *pos++ = 0x0;
  18. *pos++ = 0x0;
  19. *pos++ = 0x0;
  20. *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
  21. }
  22. static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
  23. {
  24. struct ieee80211_local *local = sdata->local;
  25. u16 capab;
  26. capab = 0;
  27. if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
  28. return capab;
  29. if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
  30. capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
  31. if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
  32. capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
  33. return capab;
  34. }
  35. static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
  36. const u8 *peer, const u8 *bssid)
  37. {
  38. struct ieee80211_tdls_lnkie *lnkid;
  39. lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
  40. lnkid->ie_type = WLAN_EID_LINK_ID;
  41. lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
  42. memcpy(lnkid->bssid, bssid, ETH_ALEN);
  43. memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
  44. memcpy(lnkid->resp_sta, peer, ETH_ALEN);
  45. }
  46. static int
  47. ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
  48. const u8 *peer, u8 action_code, u8 dialog_token,
  49. u16 status_code, struct sk_buff *skb)
  50. {
  51. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  52. enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
  53. struct ieee80211_tdls_data *tf;
  54. tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
  55. memcpy(tf->da, peer, ETH_ALEN);
  56. memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
  57. tf->ether_type = cpu_to_be16(ETH_P_TDLS);
  58. tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
  59. switch (action_code) {
  60. case WLAN_TDLS_SETUP_REQUEST:
  61. tf->category = WLAN_CATEGORY_TDLS;
  62. tf->action_code = WLAN_TDLS_SETUP_REQUEST;
  63. skb_put(skb, sizeof(tf->u.setup_req));
  64. tf->u.setup_req.dialog_token = dialog_token;
  65. tf->u.setup_req.capability =
  66. cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
  67. ieee80211_add_srates_ie(sdata, skb, false, band);
  68. ieee80211_add_ext_srates_ie(sdata, skb, false, band);
  69. ieee80211_tdls_add_ext_capab(skb);
  70. break;
  71. case WLAN_TDLS_SETUP_RESPONSE:
  72. tf->category = WLAN_CATEGORY_TDLS;
  73. tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
  74. skb_put(skb, sizeof(tf->u.setup_resp));
  75. tf->u.setup_resp.status_code = cpu_to_le16(status_code);
  76. tf->u.setup_resp.dialog_token = dialog_token;
  77. tf->u.setup_resp.capability =
  78. cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
  79. ieee80211_add_srates_ie(sdata, skb, false, band);
  80. ieee80211_add_ext_srates_ie(sdata, skb, false, band);
  81. ieee80211_tdls_add_ext_capab(skb);
  82. break;
  83. case WLAN_TDLS_SETUP_CONFIRM:
  84. tf->category = WLAN_CATEGORY_TDLS;
  85. tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
  86. skb_put(skb, sizeof(tf->u.setup_cfm));
  87. tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
  88. tf->u.setup_cfm.dialog_token = dialog_token;
  89. break;
  90. case WLAN_TDLS_TEARDOWN:
  91. tf->category = WLAN_CATEGORY_TDLS;
  92. tf->action_code = WLAN_TDLS_TEARDOWN;
  93. skb_put(skb, sizeof(tf->u.teardown));
  94. tf->u.teardown.reason_code = cpu_to_le16(status_code);
  95. break;
  96. case WLAN_TDLS_DISCOVERY_REQUEST:
  97. tf->category = WLAN_CATEGORY_TDLS;
  98. tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
  99. skb_put(skb, sizeof(tf->u.discover_req));
  100. tf->u.discover_req.dialog_token = dialog_token;
  101. break;
  102. default:
  103. return -EINVAL;
  104. }
  105. return 0;
  106. }
  107. static int
  108. ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
  109. const u8 *peer, u8 action_code, u8 dialog_token,
  110. u16 status_code, struct sk_buff *skb)
  111. {
  112. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  113. enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
  114. struct ieee80211_mgmt *mgmt;
  115. mgmt = (void *)skb_put(skb, 24);
  116. memset(mgmt, 0, 24);
  117. memcpy(mgmt->da, peer, ETH_ALEN);
  118. memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
  119. memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
  120. mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
  121. IEEE80211_STYPE_ACTION);
  122. switch (action_code) {
  123. case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
  124. skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
  125. mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
  126. mgmt->u.action.u.tdls_discover_resp.action_code =
  127. WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
  128. mgmt->u.action.u.tdls_discover_resp.dialog_token =
  129. dialog_token;
  130. mgmt->u.action.u.tdls_discover_resp.capability =
  131. cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
  132. ieee80211_add_srates_ie(sdata, skb, false, band);
  133. ieee80211_add_ext_srates_ie(sdata, skb, false, band);
  134. ieee80211_tdls_add_ext_capab(skb);
  135. break;
  136. default:
  137. return -EINVAL;
  138. }
  139. return 0;
  140. }
  141. int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  142. const u8 *peer, u8 action_code, u8 dialog_token,
  143. u16 status_code, u32 peer_capability,
  144. const u8 *extra_ies, size_t extra_ies_len)
  145. {
  146. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  147. struct ieee80211_local *local = sdata->local;
  148. struct sk_buff *skb = NULL;
  149. bool send_direct;
  150. int ret;
  151. if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
  152. return -ENOTSUPP;
  153. /* make sure we are in managed mode, and associated */
  154. if (sdata->vif.type != NL80211_IFTYPE_STATION ||
  155. !sdata->u.mgd.associated)
  156. return -EINVAL;
  157. tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n",
  158. action_code, peer);
  159. skb = dev_alloc_skb(local->hw.extra_tx_headroom +
  160. max(sizeof(struct ieee80211_mgmt),
  161. sizeof(struct ieee80211_tdls_data)) +
  162. 50 + /* supported rates */
  163. 7 + /* ext capab */
  164. extra_ies_len +
  165. sizeof(struct ieee80211_tdls_lnkie));
  166. if (!skb)
  167. return -ENOMEM;
  168. skb_reserve(skb, local->hw.extra_tx_headroom);
  169. switch (action_code) {
  170. case WLAN_TDLS_SETUP_REQUEST:
  171. case WLAN_TDLS_SETUP_RESPONSE:
  172. case WLAN_TDLS_SETUP_CONFIRM:
  173. case WLAN_TDLS_TEARDOWN:
  174. case WLAN_TDLS_DISCOVERY_REQUEST:
  175. ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
  176. action_code, dialog_token,
  177. status_code, skb);
  178. send_direct = false;
  179. break;
  180. case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
  181. ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
  182. dialog_token, status_code,
  183. skb);
  184. send_direct = true;
  185. break;
  186. default:
  187. ret = -ENOTSUPP;
  188. break;
  189. }
  190. if (ret < 0)
  191. goto fail;
  192. if (extra_ies_len)
  193. memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
  194. /* the TDLS link IE is always added last */
  195. switch (action_code) {
  196. case WLAN_TDLS_SETUP_REQUEST:
  197. case WLAN_TDLS_SETUP_CONFIRM:
  198. case WLAN_TDLS_TEARDOWN:
  199. case WLAN_TDLS_DISCOVERY_REQUEST:
  200. /* we are the initiator */
  201. ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer,
  202. sdata->u.mgd.bssid);
  203. break;
  204. case WLAN_TDLS_SETUP_RESPONSE:
  205. case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
  206. /* we are the responder */
  207. ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr,
  208. sdata->u.mgd.bssid);
  209. break;
  210. default:
  211. ret = -ENOTSUPP;
  212. goto fail;
  213. }
  214. if (send_direct) {
  215. ieee80211_tx_skb(sdata, skb);
  216. return 0;
  217. }
  218. /*
  219. * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
  220. * we should default to AC_VI.
  221. */
  222. switch (action_code) {
  223. case WLAN_TDLS_SETUP_REQUEST:
  224. case WLAN_TDLS_SETUP_RESPONSE:
  225. skb_set_queue_mapping(skb, IEEE80211_AC_BK);
  226. skb->priority = 2;
  227. break;
  228. default:
  229. skb_set_queue_mapping(skb, IEEE80211_AC_VI);
  230. skb->priority = 5;
  231. break;
  232. }
  233. /* disable bottom halves when entering the Tx path */
  234. local_bh_disable();
  235. ret = ieee80211_subif_start_xmit(skb, dev);
  236. local_bh_enable();
  237. return ret;
  238. fail:
  239. dev_kfree_skb(skb);
  240. return ret;
  241. }
  242. int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
  243. const u8 *peer, enum nl80211_tdls_operation oper)
  244. {
  245. struct sta_info *sta;
  246. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  247. if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
  248. return -ENOTSUPP;
  249. if (sdata->vif.type != NL80211_IFTYPE_STATION)
  250. return -EINVAL;
  251. tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
  252. switch (oper) {
  253. case NL80211_TDLS_ENABLE_LINK:
  254. rcu_read_lock();
  255. sta = sta_info_get(sdata, peer);
  256. if (!sta) {
  257. rcu_read_unlock();
  258. return -ENOLINK;
  259. }
  260. set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
  261. rcu_read_unlock();
  262. break;
  263. case NL80211_TDLS_DISABLE_LINK:
  264. return sta_info_destroy_addr(sdata, peer);
  265. case NL80211_TDLS_TEARDOWN:
  266. case NL80211_TDLS_SETUP:
  267. case NL80211_TDLS_DISCOVERY_REQ:
  268. /* We don't support in-driver setup/teardown/discovery */
  269. return -ENOTSUPP;
  270. default:
  271. return -ENOTSUPP;
  272. }
  273. return 0;
  274. }