mlme.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * cfg80211 MLME SAP interface
  3. *
  4. * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/module.h>
  8. #include <linux/netdevice.h>
  9. #include <linux/nl80211.h>
  10. #include <net/cfg80211.h>
  11. #include "core.h"
  12. #include "nl80211.h"
  13. void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
  14. {
  15. struct wireless_dev *wdev = dev->ieee80211_ptr;
  16. struct wiphy *wiphy = wdev->wiphy;
  17. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  18. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  19. u8 *bssid = mgmt->bssid;
  20. int i;
  21. u16 status = le16_to_cpu(mgmt->u.auth.status_code);
  22. bool done = false;
  23. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  24. if (wdev->authtry_bsses[i] &&
  25. memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
  26. ETH_ALEN) == 0) {
  27. if (status == WLAN_STATUS_SUCCESS) {
  28. wdev->auth_bsses[i] = wdev->authtry_bsses[i];
  29. } else {
  30. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  31. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  32. }
  33. wdev->authtry_bsses[i] = NULL;
  34. done = true;
  35. break;
  36. }
  37. }
  38. WARN_ON(!done);
  39. nl80211_send_rx_auth(rdev, dev, buf, len, gfp);
  40. cfg80211_sme_rx_auth(dev, buf, len);
  41. }
  42. EXPORT_SYMBOL(cfg80211_send_rx_auth);
  43. void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
  44. {
  45. u16 status_code;
  46. struct wireless_dev *wdev = dev->ieee80211_ptr;
  47. struct wiphy *wiphy = wdev->wiphy;
  48. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  49. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  50. u8 *ie = mgmt->u.assoc_resp.variable;
  51. int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
  52. bool done;
  53. status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
  54. nl80211_send_rx_assoc(rdev, dev, buf, len, gfp);
  55. cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
  56. status_code, gfp);
  57. if (status_code == WLAN_STATUS_SUCCESS) {
  58. for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) {
  59. if (wdev->auth_bsses[i] == wdev->current_bss) {
  60. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  61. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  62. wdev->auth_bsses[i] = NULL;
  63. done = true;
  64. break;
  65. }
  66. }
  67. WARN_ON(!done);
  68. }
  69. }
  70. EXPORT_SYMBOL(cfg80211_send_rx_assoc);
  71. void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
  72. {
  73. struct wireless_dev *wdev = dev->ieee80211_ptr;
  74. struct wiphy *wiphy = wdev->wiphy;
  75. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  76. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  77. const u8 *bssid = mgmt->bssid;
  78. int i;
  79. bool done = false;
  80. nl80211_send_deauth(rdev, dev, buf, len, gfp);
  81. if (wdev->current_bss &&
  82. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  83. done = true;
  84. cfg80211_unhold_bss(wdev->current_bss);
  85. cfg80211_put_bss(&wdev->current_bss->pub);
  86. wdev->current_bss = NULL;
  87. } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
  88. if (wdev->auth_bsses[i] &&
  89. memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
  90. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  91. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  92. wdev->auth_bsses[i] = NULL;
  93. done = true;
  94. break;
  95. }
  96. if (wdev->authtry_bsses[i] &&
  97. memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
  98. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  99. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  100. wdev->authtry_bsses[i] = NULL;
  101. done = true;
  102. break;
  103. }
  104. }
  105. /*
  106. * mac80211 currently triggers this warning,
  107. * so disable for now (it's harmless, just
  108. * means that we got a spurious event)
  109. WARN_ON(!done);
  110. */
  111. if (wdev->sme_state == CFG80211_SME_CONNECTED) {
  112. u16 reason_code;
  113. bool from_ap;
  114. reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
  115. from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
  116. __cfg80211_disconnected(dev, gfp, NULL, 0,
  117. reason_code, from_ap);
  118. } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
  119. cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
  120. WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
  121. }
  122. }
  123. EXPORT_SYMBOL(cfg80211_send_deauth);
  124. void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
  125. {
  126. struct wireless_dev *wdev = dev->ieee80211_ptr;
  127. struct wiphy *wiphy = wdev->wiphy;
  128. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  129. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  130. const u8 *bssid = mgmt->bssid;
  131. int i;
  132. u16 reason_code;
  133. bool from_ap;
  134. bool done = false;
  135. nl80211_send_disassoc(rdev, dev, buf, len, gfp);
  136. if (!wdev->sme_state == CFG80211_SME_CONNECTED)
  137. return;
  138. if (wdev->current_bss &&
  139. memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) {
  140. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  141. if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
  142. continue;
  143. wdev->auth_bsses[i] = wdev->current_bss;
  144. wdev->current_bss = NULL;
  145. done = true;
  146. cfg80211_sme_disassoc(dev, i);
  147. break;
  148. }
  149. WARN_ON(!done);
  150. } else
  151. WARN_ON(1);
  152. reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
  153. from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
  154. __cfg80211_disconnected(dev, gfp, NULL, 0,
  155. reason_code, from_ap);
  156. }
  157. EXPORT_SYMBOL(cfg80211_send_disassoc);
  158. void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
  159. {
  160. struct wireless_dev *wdev = dev->ieee80211_ptr;
  161. struct wiphy *wiphy = wdev->wiphy;
  162. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  163. int i;
  164. bool done = false;
  165. nl80211_send_auth_timeout(rdev, dev, addr, gfp);
  166. if (wdev->sme_state == CFG80211_SME_CONNECTING)
  167. cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
  168. WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
  169. for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
  170. if (wdev->authtry_bsses[i] &&
  171. memcmp(wdev->authtry_bsses[i]->pub.bssid,
  172. addr, ETH_ALEN) == 0) {
  173. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  174. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  175. wdev->authtry_bsses[i] = NULL;
  176. done = true;
  177. break;
  178. }
  179. }
  180. WARN_ON(!done);
  181. }
  182. EXPORT_SYMBOL(cfg80211_send_auth_timeout);
  183. void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
  184. {
  185. struct wireless_dev *wdev = dev->ieee80211_ptr;
  186. struct wiphy *wiphy = wdev->wiphy;
  187. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  188. int i;
  189. bool done = false;
  190. nl80211_send_assoc_timeout(rdev, dev, addr, gfp);
  191. if (wdev->sme_state == CFG80211_SME_CONNECTING)
  192. cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
  193. WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
  194. for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
  195. if (wdev->auth_bsses[i] &&
  196. memcmp(wdev->auth_bsses[i]->pub.bssid,
  197. addr, ETH_ALEN) == 0) {
  198. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  199. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  200. wdev->auth_bsses[i] = NULL;
  201. done = true;
  202. break;
  203. }
  204. }
  205. WARN_ON(!done);
  206. }
  207. EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
  208. void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  209. enum nl80211_key_type key_type, int key_id,
  210. const u8 *tsc, gfp_t gfp)
  211. {
  212. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  213. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  214. #ifdef CONFIG_WIRELESS_EXT
  215. union iwreq_data wrqu;
  216. char *buf = kmalloc(128, gfp);
  217. if (buf) {
  218. sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
  219. "keyid=%d %scast addr=%pM)", key_id,
  220. key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
  221. addr);
  222. memset(&wrqu, 0, sizeof(wrqu));
  223. wrqu.data.length = strlen(buf);
  224. wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
  225. kfree(buf);
  226. }
  227. #endif
  228. nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
  229. }
  230. EXPORT_SYMBOL(cfg80211_michael_mic_failure);
  231. /* some MLME handling for userspace SME */
  232. int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
  233. struct net_device *dev, struct ieee80211_channel *chan,
  234. enum nl80211_auth_type auth_type, const u8 *bssid,
  235. const u8 *ssid, int ssid_len,
  236. const u8 *ie, int ie_len)
  237. {
  238. struct wireless_dev *wdev = dev->ieee80211_ptr;
  239. struct cfg80211_auth_request req;
  240. struct cfg80211_internal_bss *bss;
  241. int i, err, slot = -1, nfree = 0;
  242. if (wdev->current_bss &&
  243. memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
  244. return -EALREADY;
  245. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  246. if (wdev->authtry_bsses[i] &&
  247. memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid,
  248. ETH_ALEN) == 0)
  249. return -EALREADY;
  250. if (wdev->auth_bsses[i] &&
  251. memcmp(bssid, wdev->auth_bsses[i]->pub.bssid,
  252. ETH_ALEN) == 0)
  253. return -EALREADY;
  254. }
  255. memset(&req, 0, sizeof(req));
  256. req.ie = ie;
  257. req.ie_len = ie_len;
  258. req.auth_type = auth_type;
  259. req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
  260. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  261. if (!req.bss)
  262. return -ENOENT;
  263. bss = bss_from_pub(req.bss);
  264. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  265. if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) {
  266. slot = i;
  267. nfree++;
  268. }
  269. }
  270. /* we need one free slot for disassoc and one for this auth */
  271. if (nfree < 2) {
  272. err = -ENOSPC;
  273. goto out;
  274. }
  275. wdev->authtry_bsses[slot] = bss;
  276. cfg80211_hold_bss(bss);
  277. err = rdev->ops->auth(&rdev->wiphy, dev, &req);
  278. if (err) {
  279. wdev->authtry_bsses[slot] = NULL;
  280. cfg80211_unhold_bss(bss);
  281. }
  282. out:
  283. if (err)
  284. cfg80211_put_bss(req.bss);
  285. return err;
  286. }
  287. int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
  288. struct net_device *dev, struct ieee80211_channel *chan,
  289. const u8 *bssid, const u8 *prev_bssid,
  290. const u8 *ssid, int ssid_len,
  291. const u8 *ie, int ie_len, bool use_mfp,
  292. struct cfg80211_crypto_settings *crypt)
  293. {
  294. struct wireless_dev *wdev = dev->ieee80211_ptr;
  295. struct cfg80211_assoc_request req;
  296. struct cfg80211_internal_bss *bss;
  297. int i, err, slot = -1;
  298. memset(&req, 0, sizeof(req));
  299. if (wdev->current_bss)
  300. return -EALREADY;
  301. req.ie = ie;
  302. req.ie_len = ie_len;
  303. memcpy(&req.crypto, crypt, sizeof(req.crypto));
  304. req.use_mfp = use_mfp;
  305. req.prev_bssid = prev_bssid;
  306. req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
  307. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  308. if (!req.bss)
  309. return -ENOENT;
  310. bss = bss_from_pub(req.bss);
  311. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  312. if (bss == wdev->auth_bsses[i]) {
  313. slot = i;
  314. break;
  315. }
  316. }
  317. if (slot < 0) {
  318. err = -ENOTCONN;
  319. goto out;
  320. }
  321. err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
  322. out:
  323. /* still a reference in wdev->auth_bsses[slot] */
  324. cfg80211_put_bss(req.bss);
  325. return err;
  326. }
  327. int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
  328. struct net_device *dev, const u8 *bssid,
  329. const u8 *ie, int ie_len, u16 reason)
  330. {
  331. struct wireless_dev *wdev = dev->ieee80211_ptr;
  332. struct cfg80211_deauth_request req;
  333. int i;
  334. memset(&req, 0, sizeof(req));
  335. req.reason_code = reason;
  336. req.ie = ie;
  337. req.ie_len = ie_len;
  338. if (wdev->current_bss &&
  339. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  340. req.bss = &wdev->current_bss->pub;
  341. } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
  342. if (wdev->auth_bsses[i] &&
  343. memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
  344. req.bss = &wdev->auth_bsses[i]->pub;
  345. break;
  346. }
  347. if (wdev->authtry_bsses[i] &&
  348. memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
  349. req.bss = &wdev->authtry_bsses[i]->pub;
  350. break;
  351. }
  352. }
  353. if (!req.bss)
  354. return -ENOTCONN;
  355. return rdev->ops->deauth(&rdev->wiphy, dev, &req);
  356. }
  357. int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
  358. struct net_device *dev, const u8 *bssid,
  359. const u8 *ie, int ie_len, u16 reason)
  360. {
  361. struct wireless_dev *wdev = dev->ieee80211_ptr;
  362. struct cfg80211_disassoc_request req;
  363. memset(&req, 0, sizeof(req));
  364. req.reason_code = reason;
  365. req.ie = ie;
  366. req.ie_len = ie_len;
  367. if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
  368. req.bss = &wdev->current_bss->pub;
  369. else
  370. return -ENOTCONN;
  371. return rdev->ops->disassoc(&rdev->wiphy, dev, &req);
  372. }
  373. void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
  374. struct net_device *dev)
  375. {
  376. struct wireless_dev *wdev = dev->ieee80211_ptr;
  377. struct cfg80211_deauth_request req;
  378. int i;
  379. if (!rdev->ops->deauth)
  380. return;
  381. memset(&req, 0, sizeof(req));
  382. req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
  383. req.ie = NULL;
  384. req.ie_len = 0;
  385. if (wdev->current_bss) {
  386. req.bss = &wdev->current_bss->pub;
  387. rdev->ops->deauth(&rdev->wiphy, dev, &req);
  388. if (wdev->current_bss) {
  389. cfg80211_unhold_bss(wdev->current_bss);
  390. cfg80211_put_bss(&wdev->current_bss->pub);
  391. wdev->current_bss = NULL;
  392. }
  393. }
  394. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  395. if (wdev->auth_bsses[i]) {
  396. req.bss = &wdev->auth_bsses[i]->pub;
  397. rdev->ops->deauth(&rdev->wiphy, dev, &req);
  398. if (wdev->auth_bsses[i]) {
  399. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  400. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  401. wdev->auth_bsses[i] = NULL;
  402. }
  403. }
  404. if (wdev->authtry_bsses[i]) {
  405. req.bss = &wdev->authtry_bsses[i]->pub;
  406. rdev->ops->deauth(&rdev->wiphy, dev, &req);
  407. if (wdev->authtry_bsses[i]) {
  408. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  409. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  410. wdev->authtry_bsses[i] = NULL;
  411. }
  412. }
  413. }
  414. }