mlme.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  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 <linux/wireless.h>
  11. #include <net/cfg80211.h>
  12. #include <net/iw_handler.h>
  13. #include "core.h"
  14. #include "nl80211.h"
  15. void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
  16. {
  17. struct wireless_dev *wdev = dev->ieee80211_ptr;
  18. struct wiphy *wiphy = wdev->wiphy;
  19. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  20. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  21. u8 *bssid = mgmt->bssid;
  22. int i;
  23. u16 status = le16_to_cpu(mgmt->u.auth.status_code);
  24. bool done = false;
  25. wdev_lock(wdev);
  26. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  27. if (wdev->authtry_bsses[i] &&
  28. memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
  29. ETH_ALEN) == 0) {
  30. if (status == WLAN_STATUS_SUCCESS) {
  31. wdev->auth_bsses[i] = wdev->authtry_bsses[i];
  32. } else {
  33. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  34. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  35. }
  36. wdev->authtry_bsses[i] = NULL;
  37. done = true;
  38. break;
  39. }
  40. }
  41. WARN_ON(!done);
  42. nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
  43. cfg80211_sme_rx_auth(dev, buf, len);
  44. wdev_unlock(wdev);
  45. }
  46. EXPORT_SYMBOL(cfg80211_send_rx_auth);
  47. void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
  48. {
  49. u16 status_code;
  50. struct wireless_dev *wdev = dev->ieee80211_ptr;
  51. struct wiphy *wiphy = wdev->wiphy;
  52. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  53. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  54. u8 *ie = mgmt->u.assoc_resp.variable;
  55. int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
  56. struct cfg80211_internal_bss *bss = NULL;
  57. bool need_connect_result = true;
  58. wdev_lock(wdev);
  59. status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
  60. /*
  61. * This is a bit of a hack, we don't notify userspace of
  62. * a (re-)association reply if we tried to send a reassoc
  63. * and got a reject -- we only try again with an assoc
  64. * frame instead of reassoc.
  65. */
  66. if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
  67. cfg80211_sme_failed_reassoc(wdev))
  68. goto out;
  69. nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
  70. if (status_code == WLAN_STATUS_SUCCESS) {
  71. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  72. if (!wdev->auth_bsses[i])
  73. continue;
  74. if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid,
  75. ETH_ALEN) == 0) {
  76. bss = wdev->auth_bsses[i];
  77. wdev->auth_bsses[i] = NULL;
  78. /* additional reference to drop hold */
  79. cfg80211_ref_bss(bss);
  80. break;
  81. }
  82. }
  83. WARN_ON(!bss);
  84. } else if (wdev->conn) {
  85. cfg80211_sme_failed_assoc(wdev);
  86. need_connect_result = false;
  87. /*
  88. * do not call connect_result() now because the
  89. * sme will schedule work that does it later.
  90. */
  91. goto out;
  92. }
  93. if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
  94. /*
  95. * This is for the userspace SME, the CONNECTING
  96. * state will be changed to CONNECTED by
  97. * __cfg80211_connect_result() below.
  98. */
  99. wdev->sme_state = CFG80211_SME_CONNECTING;
  100. }
  101. /* this consumes one bss reference (unless bss is NULL) */
  102. __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
  103. status_code,
  104. status_code == WLAN_STATUS_SUCCESS,
  105. bss ? &bss->pub : NULL);
  106. /* drop hold now, and also reference acquired above */
  107. if (bss) {
  108. cfg80211_unhold_bss(bss);
  109. cfg80211_put_bss(&bss->pub);
  110. }
  111. out:
  112. wdev_unlock(wdev);
  113. }
  114. EXPORT_SYMBOL(cfg80211_send_rx_assoc);
  115. static void __cfg80211_send_deauth(struct net_device *dev,
  116. const u8 *buf, size_t len)
  117. {
  118. struct wireless_dev *wdev = dev->ieee80211_ptr;
  119. struct wiphy *wiphy = wdev->wiphy;
  120. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  121. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  122. const u8 *bssid = mgmt->bssid;
  123. int i;
  124. bool done = false;
  125. ASSERT_WDEV_LOCK(wdev);
  126. nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
  127. if (wdev->current_bss &&
  128. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  129. done = true;
  130. cfg80211_unhold_bss(wdev->current_bss);
  131. cfg80211_put_bss(&wdev->current_bss->pub);
  132. wdev->current_bss = NULL;
  133. } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
  134. if (wdev->auth_bsses[i] &&
  135. memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
  136. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  137. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  138. wdev->auth_bsses[i] = NULL;
  139. done = true;
  140. break;
  141. }
  142. if (wdev->authtry_bsses[i] &&
  143. memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
  144. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  145. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  146. wdev->authtry_bsses[i] = NULL;
  147. done = true;
  148. break;
  149. }
  150. }
  151. WARN_ON(!done);
  152. if (wdev->sme_state == CFG80211_SME_CONNECTED) {
  153. u16 reason_code;
  154. bool from_ap;
  155. reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
  156. from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
  157. __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
  158. } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
  159. __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
  160. WLAN_STATUS_UNSPECIFIED_FAILURE,
  161. false, NULL);
  162. }
  163. }
  164. void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
  165. void *cookie)
  166. {
  167. struct wireless_dev *wdev = dev->ieee80211_ptr;
  168. BUG_ON(cookie && wdev != cookie);
  169. if (cookie) {
  170. /* called within callback */
  171. __cfg80211_send_deauth(dev, buf, len);
  172. } else {
  173. wdev_lock(wdev);
  174. __cfg80211_send_deauth(dev, buf, len);
  175. wdev_unlock(wdev);
  176. }
  177. }
  178. EXPORT_SYMBOL(cfg80211_send_deauth);
  179. static void __cfg80211_send_disassoc(struct net_device *dev,
  180. const u8 *buf, size_t len)
  181. {
  182. struct wireless_dev *wdev = dev->ieee80211_ptr;
  183. struct wiphy *wiphy = wdev->wiphy;
  184. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  185. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  186. const u8 *bssid = mgmt->bssid;
  187. int i;
  188. u16 reason_code;
  189. bool from_ap;
  190. bool done = false;
  191. ASSERT_WDEV_LOCK(wdev);
  192. nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
  193. if (wdev->sme_state != CFG80211_SME_CONNECTED)
  194. return;
  195. if (wdev->current_bss &&
  196. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  197. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  198. if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
  199. continue;
  200. wdev->auth_bsses[i] = wdev->current_bss;
  201. wdev->current_bss = NULL;
  202. done = true;
  203. cfg80211_sme_disassoc(dev, i);
  204. break;
  205. }
  206. WARN_ON(!done);
  207. } else
  208. WARN_ON(1);
  209. reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
  210. from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
  211. __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
  212. }
  213. void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
  214. void *cookie)
  215. {
  216. struct wireless_dev *wdev = dev->ieee80211_ptr;
  217. BUG_ON(cookie && wdev != cookie);
  218. if (cookie) {
  219. /* called within callback */
  220. __cfg80211_send_disassoc(dev, buf, len);
  221. } else {
  222. wdev_lock(wdev);
  223. __cfg80211_send_disassoc(dev, buf, len);
  224. wdev_unlock(wdev);
  225. }
  226. }
  227. EXPORT_SYMBOL(cfg80211_send_disassoc);
  228. void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
  229. {
  230. struct wireless_dev *wdev = dev->ieee80211_ptr;
  231. struct wiphy *wiphy = wdev->wiphy;
  232. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  233. int i;
  234. bool done = false;
  235. wdev_lock(wdev);
  236. nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
  237. if (wdev->sme_state == CFG80211_SME_CONNECTING)
  238. __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
  239. WLAN_STATUS_UNSPECIFIED_FAILURE,
  240. false, NULL);
  241. for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
  242. if (wdev->authtry_bsses[i] &&
  243. memcmp(wdev->authtry_bsses[i]->pub.bssid,
  244. addr, ETH_ALEN) == 0) {
  245. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  246. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  247. wdev->authtry_bsses[i] = NULL;
  248. done = true;
  249. break;
  250. }
  251. }
  252. WARN_ON(!done);
  253. wdev_unlock(wdev);
  254. }
  255. EXPORT_SYMBOL(cfg80211_send_auth_timeout);
  256. void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
  257. {
  258. struct wireless_dev *wdev = dev->ieee80211_ptr;
  259. struct wiphy *wiphy = wdev->wiphy;
  260. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  261. int i;
  262. bool done = false;
  263. wdev_lock(wdev);
  264. nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
  265. if (wdev->sme_state == CFG80211_SME_CONNECTING)
  266. __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
  267. WLAN_STATUS_UNSPECIFIED_FAILURE,
  268. false, NULL);
  269. for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
  270. if (wdev->auth_bsses[i] &&
  271. memcmp(wdev->auth_bsses[i]->pub.bssid,
  272. addr, ETH_ALEN) == 0) {
  273. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  274. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  275. wdev->auth_bsses[i] = NULL;
  276. done = true;
  277. break;
  278. }
  279. }
  280. WARN_ON(!done);
  281. wdev_unlock(wdev);
  282. }
  283. EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
  284. void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  285. enum nl80211_key_type key_type, int key_id,
  286. const u8 *tsc, gfp_t gfp)
  287. {
  288. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  289. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  290. #ifdef CONFIG_WIRELESS_EXT
  291. union iwreq_data wrqu;
  292. char *buf = kmalloc(128, gfp);
  293. if (buf) {
  294. sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
  295. "keyid=%d %scast addr=%pM)", key_id,
  296. key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
  297. addr);
  298. memset(&wrqu, 0, sizeof(wrqu));
  299. wrqu.data.length = strlen(buf);
  300. wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
  301. kfree(buf);
  302. }
  303. #endif
  304. nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
  305. }
  306. EXPORT_SYMBOL(cfg80211_michael_mic_failure);
  307. /* some MLME handling for userspace SME */
  308. int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
  309. struct net_device *dev,
  310. struct ieee80211_channel *chan,
  311. enum nl80211_auth_type auth_type,
  312. const u8 *bssid,
  313. const u8 *ssid, int ssid_len,
  314. const u8 *ie, int ie_len,
  315. const u8 *key, int key_len, int key_idx)
  316. {
  317. struct wireless_dev *wdev = dev->ieee80211_ptr;
  318. struct cfg80211_auth_request req;
  319. struct cfg80211_internal_bss *bss;
  320. int i, err, slot = -1, nfree = 0;
  321. ASSERT_WDEV_LOCK(wdev);
  322. if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
  323. if (!key || !key_len || key_idx < 0 || key_idx > 4)
  324. return -EINVAL;
  325. if (wdev->current_bss &&
  326. memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
  327. return -EALREADY;
  328. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  329. if (wdev->authtry_bsses[i] &&
  330. memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid,
  331. ETH_ALEN) == 0)
  332. return -EALREADY;
  333. if (wdev->auth_bsses[i] &&
  334. memcmp(bssid, wdev->auth_bsses[i]->pub.bssid,
  335. ETH_ALEN) == 0)
  336. return -EALREADY;
  337. }
  338. memset(&req, 0, sizeof(req));
  339. req.ie = ie;
  340. req.ie_len = ie_len;
  341. req.auth_type = auth_type;
  342. req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
  343. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  344. req.key = key;
  345. req.key_len = key_len;
  346. req.key_idx = key_idx;
  347. if (!req.bss)
  348. return -ENOENT;
  349. bss = bss_from_pub(req.bss);
  350. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  351. if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) {
  352. slot = i;
  353. nfree++;
  354. }
  355. }
  356. /* we need one free slot for disassoc and one for this auth */
  357. if (nfree < 2) {
  358. err = -ENOSPC;
  359. goto out;
  360. }
  361. wdev->authtry_bsses[slot] = bss;
  362. cfg80211_hold_bss(bss);
  363. err = rdev->ops->auth(&rdev->wiphy, dev, &req);
  364. if (err) {
  365. wdev->authtry_bsses[slot] = NULL;
  366. cfg80211_unhold_bss(bss);
  367. }
  368. out:
  369. if (err)
  370. cfg80211_put_bss(req.bss);
  371. return err;
  372. }
  373. int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
  374. struct net_device *dev, struct ieee80211_channel *chan,
  375. enum nl80211_auth_type auth_type, const u8 *bssid,
  376. const u8 *ssid, int ssid_len,
  377. const u8 *ie, int ie_len,
  378. const u8 *key, int key_len, int key_idx)
  379. {
  380. int err;
  381. wdev_lock(dev->ieee80211_ptr);
  382. err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
  383. ssid, ssid_len, ie, ie_len,
  384. key, key_len, key_idx);
  385. wdev_unlock(dev->ieee80211_ptr);
  386. return err;
  387. }
  388. int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
  389. struct net_device *dev,
  390. struct ieee80211_channel *chan,
  391. const u8 *bssid, const u8 *prev_bssid,
  392. const u8 *ssid, int ssid_len,
  393. const u8 *ie, int ie_len, bool use_mfp,
  394. struct cfg80211_crypto_settings *crypt)
  395. {
  396. struct wireless_dev *wdev = dev->ieee80211_ptr;
  397. struct cfg80211_assoc_request req;
  398. struct cfg80211_internal_bss *bss;
  399. int i, err, slot = -1;
  400. ASSERT_WDEV_LOCK(wdev);
  401. memset(&req, 0, sizeof(req));
  402. if (wdev->current_bss)
  403. return -EALREADY;
  404. req.ie = ie;
  405. req.ie_len = ie_len;
  406. memcpy(&req.crypto, crypt, sizeof(req.crypto));
  407. req.use_mfp = use_mfp;
  408. req.prev_bssid = prev_bssid;
  409. req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
  410. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  411. if (!req.bss)
  412. return -ENOENT;
  413. bss = bss_from_pub(req.bss);
  414. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  415. if (bss == wdev->auth_bsses[i]) {
  416. slot = i;
  417. break;
  418. }
  419. }
  420. if (slot < 0) {
  421. err = -ENOTCONN;
  422. goto out;
  423. }
  424. err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
  425. out:
  426. /* still a reference in wdev->auth_bsses[slot] */
  427. cfg80211_put_bss(req.bss);
  428. return err;
  429. }
  430. int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
  431. struct net_device *dev,
  432. struct ieee80211_channel *chan,
  433. const u8 *bssid, const u8 *prev_bssid,
  434. const u8 *ssid, int ssid_len,
  435. const u8 *ie, int ie_len, bool use_mfp,
  436. struct cfg80211_crypto_settings *crypt)
  437. {
  438. struct wireless_dev *wdev = dev->ieee80211_ptr;
  439. int err;
  440. wdev_lock(wdev);
  441. err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
  442. ssid, ssid_len, ie, ie_len, use_mfp, crypt);
  443. wdev_unlock(wdev);
  444. return err;
  445. }
  446. int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
  447. struct net_device *dev, const u8 *bssid,
  448. const u8 *ie, int ie_len, u16 reason)
  449. {
  450. struct wireless_dev *wdev = dev->ieee80211_ptr;
  451. struct cfg80211_deauth_request req;
  452. int i;
  453. ASSERT_WDEV_LOCK(wdev);
  454. memset(&req, 0, sizeof(req));
  455. req.reason_code = reason;
  456. req.ie = ie;
  457. req.ie_len = ie_len;
  458. if (wdev->current_bss &&
  459. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  460. req.bss = &wdev->current_bss->pub;
  461. } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
  462. if (wdev->auth_bsses[i] &&
  463. memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
  464. req.bss = &wdev->auth_bsses[i]->pub;
  465. break;
  466. }
  467. if (wdev->authtry_bsses[i] &&
  468. memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
  469. req.bss = &wdev->authtry_bsses[i]->pub;
  470. break;
  471. }
  472. }
  473. if (!req.bss)
  474. return -ENOTCONN;
  475. return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  476. }
  477. int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
  478. struct net_device *dev, const u8 *bssid,
  479. const u8 *ie, int ie_len, u16 reason)
  480. {
  481. struct wireless_dev *wdev = dev->ieee80211_ptr;
  482. int err;
  483. wdev_lock(wdev);
  484. err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason);
  485. wdev_unlock(wdev);
  486. return err;
  487. }
  488. static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
  489. struct net_device *dev, const u8 *bssid,
  490. const u8 *ie, int ie_len, u16 reason)
  491. {
  492. struct wireless_dev *wdev = dev->ieee80211_ptr;
  493. struct cfg80211_disassoc_request req;
  494. ASSERT_WDEV_LOCK(wdev);
  495. if (wdev->sme_state != CFG80211_SME_CONNECTED)
  496. return -ENOTCONN;
  497. if (WARN_ON(!wdev->current_bss))
  498. return -ENOTCONN;
  499. memset(&req, 0, sizeof(req));
  500. req.reason_code = reason;
  501. req.ie = ie;
  502. req.ie_len = ie_len;
  503. if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
  504. req.bss = &wdev->current_bss->pub;
  505. else
  506. return -ENOTCONN;
  507. return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev);
  508. }
  509. int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
  510. struct net_device *dev, const u8 *bssid,
  511. const u8 *ie, int ie_len, u16 reason)
  512. {
  513. struct wireless_dev *wdev = dev->ieee80211_ptr;
  514. int err;
  515. wdev_lock(wdev);
  516. err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason);
  517. wdev_unlock(wdev);
  518. return err;
  519. }
  520. void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
  521. struct net_device *dev)
  522. {
  523. struct wireless_dev *wdev = dev->ieee80211_ptr;
  524. struct cfg80211_deauth_request req;
  525. int i;
  526. ASSERT_WDEV_LOCK(wdev);
  527. if (!rdev->ops->deauth)
  528. return;
  529. memset(&req, 0, sizeof(req));
  530. req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
  531. req.ie = NULL;
  532. req.ie_len = 0;
  533. if (wdev->current_bss) {
  534. req.bss = &wdev->current_bss->pub;
  535. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  536. if (wdev->current_bss) {
  537. cfg80211_unhold_bss(wdev->current_bss);
  538. cfg80211_put_bss(&wdev->current_bss->pub);
  539. wdev->current_bss = NULL;
  540. }
  541. }
  542. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  543. if (wdev->auth_bsses[i]) {
  544. req.bss = &wdev->auth_bsses[i]->pub;
  545. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  546. if (wdev->auth_bsses[i]) {
  547. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  548. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  549. wdev->auth_bsses[i] = NULL;
  550. }
  551. }
  552. if (wdev->authtry_bsses[i]) {
  553. req.bss = &wdev->authtry_bsses[i]->pub;
  554. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  555. if (wdev->authtry_bsses[i]) {
  556. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  557. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  558. wdev->authtry_bsses[i] = NULL;
  559. }
  560. }
  561. }
  562. }