mlme.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  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/slab.h>
  11. #include <linux/wireless.h>
  12. #include <net/cfg80211.h>
  13. #include <net/iw_handler.h>
  14. #include "core.h"
  15. #include "nl80211.h"
  16. void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
  17. {
  18. struct wireless_dev *wdev = dev->ieee80211_ptr;
  19. struct wiphy *wiphy = wdev->wiphy;
  20. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  21. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  22. u8 *bssid = mgmt->bssid;
  23. int i;
  24. u16 status = le16_to_cpu(mgmt->u.auth.status_code);
  25. bool done = false;
  26. wdev_lock(wdev);
  27. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  28. if (wdev->authtry_bsses[i] &&
  29. memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
  30. ETH_ALEN) == 0) {
  31. if (status == WLAN_STATUS_SUCCESS) {
  32. wdev->auth_bsses[i] = wdev->authtry_bsses[i];
  33. } else {
  34. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  35. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  36. }
  37. wdev->authtry_bsses[i] = NULL;
  38. done = true;
  39. break;
  40. }
  41. }
  42. if (done) {
  43. nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
  44. cfg80211_sme_rx_auth(dev, buf, len);
  45. }
  46. wdev_unlock(wdev);
  47. }
  48. EXPORT_SYMBOL(cfg80211_send_rx_auth);
  49. void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
  50. {
  51. u16 status_code;
  52. struct wireless_dev *wdev = dev->ieee80211_ptr;
  53. struct wiphy *wiphy = wdev->wiphy;
  54. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  55. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  56. u8 *ie = mgmt->u.assoc_resp.variable;
  57. int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
  58. struct cfg80211_internal_bss *bss = NULL;
  59. wdev_lock(wdev);
  60. status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
  61. /*
  62. * This is a bit of a hack, we don't notify userspace of
  63. * a (re-)association reply if we tried to send a reassoc
  64. * and got a reject -- we only try again with an assoc
  65. * frame instead of reassoc.
  66. */
  67. if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
  68. cfg80211_sme_failed_reassoc(wdev))
  69. goto out;
  70. nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
  71. if (status_code == WLAN_STATUS_SUCCESS) {
  72. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  73. if (!wdev->auth_bsses[i])
  74. continue;
  75. if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid,
  76. ETH_ALEN) == 0) {
  77. bss = wdev->auth_bsses[i];
  78. wdev->auth_bsses[i] = NULL;
  79. /* additional reference to drop hold */
  80. cfg80211_ref_bss(bss);
  81. break;
  82. }
  83. }
  84. /*
  85. * We might be coming here because the driver reported
  86. * a successful association at the same time as the
  87. * user requested a deauth. In that case, we will have
  88. * removed the BSS from the auth_bsses list due to the
  89. * deauth request when the assoc response makes it. If
  90. * the two code paths acquire the lock the other way
  91. * around, that's just the standard situation of a
  92. * deauth being requested while connected.
  93. */
  94. if (!bss)
  95. goto out;
  96. } else if (wdev->conn) {
  97. cfg80211_sme_failed_assoc(wdev);
  98. /*
  99. * do not call connect_result() now because the
  100. * sme will schedule work that does it later.
  101. */
  102. goto out;
  103. }
  104. if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
  105. /*
  106. * This is for the userspace SME, the CONNECTING
  107. * state will be changed to CONNECTED by
  108. * __cfg80211_connect_result() below.
  109. */
  110. wdev->sme_state = CFG80211_SME_CONNECTING;
  111. }
  112. /* this consumes one bss reference (unless bss is NULL) */
  113. __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
  114. status_code,
  115. status_code == WLAN_STATUS_SUCCESS,
  116. bss ? &bss->pub : NULL);
  117. /* drop hold now, and also reference acquired above */
  118. if (bss) {
  119. cfg80211_unhold_bss(bss);
  120. cfg80211_put_bss(&bss->pub);
  121. }
  122. out:
  123. wdev_unlock(wdev);
  124. }
  125. EXPORT_SYMBOL(cfg80211_send_rx_assoc);
  126. void __cfg80211_send_deauth(struct net_device *dev,
  127. const u8 *buf, size_t len)
  128. {
  129. struct wireless_dev *wdev = dev->ieee80211_ptr;
  130. struct wiphy *wiphy = wdev->wiphy;
  131. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  132. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  133. const u8 *bssid = mgmt->bssid;
  134. int i;
  135. bool found = false;
  136. ASSERT_WDEV_LOCK(wdev);
  137. if (wdev->current_bss &&
  138. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  139. cfg80211_unhold_bss(wdev->current_bss);
  140. cfg80211_put_bss(&wdev->current_bss->pub);
  141. wdev->current_bss = NULL;
  142. found = true;
  143. } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
  144. if (wdev->auth_bsses[i] &&
  145. memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
  146. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  147. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  148. wdev->auth_bsses[i] = NULL;
  149. found = true;
  150. break;
  151. }
  152. if (wdev->authtry_bsses[i] &&
  153. memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
  154. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  155. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  156. wdev->authtry_bsses[i] = NULL;
  157. found = true;
  158. break;
  159. }
  160. }
  161. if (!found)
  162. return;
  163. nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
  164. if (wdev->sme_state == CFG80211_SME_CONNECTED) {
  165. u16 reason_code;
  166. bool from_ap;
  167. reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
  168. from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
  169. __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
  170. } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
  171. __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
  172. WLAN_STATUS_UNSPECIFIED_FAILURE,
  173. false, NULL);
  174. }
  175. }
  176. EXPORT_SYMBOL(__cfg80211_send_deauth);
  177. void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
  178. {
  179. struct wireless_dev *wdev = dev->ieee80211_ptr;
  180. wdev_lock(wdev);
  181. __cfg80211_send_deauth(dev, buf, len);
  182. wdev_unlock(wdev);
  183. }
  184. EXPORT_SYMBOL(cfg80211_send_deauth);
  185. void __cfg80211_send_disassoc(struct net_device *dev,
  186. const u8 *buf, size_t len)
  187. {
  188. struct wireless_dev *wdev = dev->ieee80211_ptr;
  189. struct wiphy *wiphy = wdev->wiphy;
  190. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  191. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  192. const u8 *bssid = mgmt->bssid;
  193. int i;
  194. u16 reason_code;
  195. bool from_ap;
  196. bool done = false;
  197. ASSERT_WDEV_LOCK(wdev);
  198. nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
  199. if (wdev->sme_state != CFG80211_SME_CONNECTED)
  200. return;
  201. if (wdev->current_bss &&
  202. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  203. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  204. if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
  205. continue;
  206. wdev->auth_bsses[i] = wdev->current_bss;
  207. wdev->current_bss = NULL;
  208. done = true;
  209. cfg80211_sme_disassoc(dev, i);
  210. break;
  211. }
  212. WARN_ON(!done);
  213. } else
  214. WARN_ON(1);
  215. reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
  216. from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
  217. __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
  218. }
  219. EXPORT_SYMBOL(__cfg80211_send_disassoc);
  220. void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
  221. {
  222. struct wireless_dev *wdev = dev->ieee80211_ptr;
  223. wdev_lock(wdev);
  224. __cfg80211_send_disassoc(dev, buf, len);
  225. wdev_unlock(wdev);
  226. }
  227. EXPORT_SYMBOL(cfg80211_send_disassoc);
  228. static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr)
  229. {
  230. int i;
  231. bool done = false;
  232. ASSERT_WDEV_LOCK(wdev);
  233. for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
  234. if (wdev->authtry_bsses[i] &&
  235. memcmp(wdev->authtry_bsses[i]->pub.bssid,
  236. addr, ETH_ALEN) == 0) {
  237. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  238. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  239. wdev->authtry_bsses[i] = NULL;
  240. done = true;
  241. break;
  242. }
  243. }
  244. WARN_ON(!done);
  245. }
  246. void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr)
  247. {
  248. __cfg80211_auth_remove(dev->ieee80211_ptr, addr);
  249. }
  250. EXPORT_SYMBOL(__cfg80211_auth_canceled);
  251. void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
  252. {
  253. struct wireless_dev *wdev = dev->ieee80211_ptr;
  254. struct wiphy *wiphy = wdev->wiphy;
  255. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  256. wdev_lock(wdev);
  257. nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
  258. if (wdev->sme_state == CFG80211_SME_CONNECTING)
  259. __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
  260. WLAN_STATUS_UNSPECIFIED_FAILURE,
  261. false, NULL);
  262. __cfg80211_auth_remove(wdev, addr);
  263. wdev_unlock(wdev);
  264. }
  265. EXPORT_SYMBOL(cfg80211_send_auth_timeout);
  266. void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
  267. {
  268. struct wireless_dev *wdev = dev->ieee80211_ptr;
  269. struct wiphy *wiphy = wdev->wiphy;
  270. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  271. int i;
  272. bool done = false;
  273. wdev_lock(wdev);
  274. nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
  275. if (wdev->sme_state == CFG80211_SME_CONNECTING)
  276. __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
  277. WLAN_STATUS_UNSPECIFIED_FAILURE,
  278. false, NULL);
  279. for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
  280. if (wdev->auth_bsses[i] &&
  281. memcmp(wdev->auth_bsses[i]->pub.bssid,
  282. addr, ETH_ALEN) == 0) {
  283. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  284. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  285. wdev->auth_bsses[i] = NULL;
  286. done = true;
  287. break;
  288. }
  289. }
  290. WARN_ON(!done);
  291. wdev_unlock(wdev);
  292. }
  293. EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
  294. void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  295. enum nl80211_key_type key_type, int key_id,
  296. const u8 *tsc, gfp_t gfp)
  297. {
  298. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  299. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  300. #ifdef CONFIG_CFG80211_WEXT
  301. union iwreq_data wrqu;
  302. char *buf = kmalloc(128, gfp);
  303. if (buf) {
  304. sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
  305. "keyid=%d %scast addr=%pM)", key_id,
  306. key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
  307. addr);
  308. memset(&wrqu, 0, sizeof(wrqu));
  309. wrqu.data.length = strlen(buf);
  310. wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
  311. kfree(buf);
  312. }
  313. #endif
  314. nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
  315. }
  316. EXPORT_SYMBOL(cfg80211_michael_mic_failure);
  317. /* some MLME handling for userspace SME */
  318. int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
  319. struct net_device *dev,
  320. struct ieee80211_channel *chan,
  321. enum nl80211_auth_type auth_type,
  322. const u8 *bssid,
  323. const u8 *ssid, int ssid_len,
  324. const u8 *ie, int ie_len,
  325. const u8 *key, int key_len, int key_idx,
  326. bool local_state_change)
  327. {
  328. struct wireless_dev *wdev = dev->ieee80211_ptr;
  329. struct cfg80211_auth_request req;
  330. struct cfg80211_internal_bss *bss;
  331. int i, err, slot = -1, nfree = 0;
  332. ASSERT_WDEV_LOCK(wdev);
  333. if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
  334. if (!key || !key_len || key_idx < 0 || key_idx > 4)
  335. return -EINVAL;
  336. if (wdev->current_bss &&
  337. memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
  338. return -EALREADY;
  339. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  340. if (wdev->authtry_bsses[i] &&
  341. memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid,
  342. ETH_ALEN) == 0)
  343. return -EALREADY;
  344. if (wdev->auth_bsses[i] &&
  345. memcmp(bssid, wdev->auth_bsses[i]->pub.bssid,
  346. ETH_ALEN) == 0)
  347. return -EALREADY;
  348. }
  349. memset(&req, 0, sizeof(req));
  350. req.local_state_change = local_state_change;
  351. req.ie = ie;
  352. req.ie_len = ie_len;
  353. req.auth_type = auth_type;
  354. req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
  355. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  356. req.key = key;
  357. req.key_len = key_len;
  358. req.key_idx = key_idx;
  359. if (!req.bss)
  360. return -ENOENT;
  361. bss = bss_from_pub(req.bss);
  362. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  363. if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) {
  364. slot = i;
  365. nfree++;
  366. }
  367. }
  368. /* we need one free slot for disassoc and one for this auth */
  369. if (nfree < 2) {
  370. err = -ENOSPC;
  371. goto out;
  372. }
  373. if (local_state_change)
  374. wdev->auth_bsses[slot] = bss;
  375. else
  376. wdev->authtry_bsses[slot] = bss;
  377. cfg80211_hold_bss(bss);
  378. err = rdev->ops->auth(&rdev->wiphy, dev, &req);
  379. if (err) {
  380. if (local_state_change)
  381. wdev->auth_bsses[slot] = NULL;
  382. else
  383. wdev->authtry_bsses[slot] = NULL;
  384. cfg80211_unhold_bss(bss);
  385. }
  386. out:
  387. if (err)
  388. cfg80211_put_bss(req.bss);
  389. return err;
  390. }
  391. int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
  392. struct net_device *dev, struct ieee80211_channel *chan,
  393. enum nl80211_auth_type auth_type, const u8 *bssid,
  394. const u8 *ssid, int ssid_len,
  395. const u8 *ie, int ie_len,
  396. const u8 *key, int key_len, int key_idx,
  397. bool local_state_change)
  398. {
  399. int err;
  400. wdev_lock(dev->ieee80211_ptr);
  401. err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
  402. ssid, ssid_len, ie, ie_len,
  403. key, key_len, key_idx, local_state_change);
  404. wdev_unlock(dev->ieee80211_ptr);
  405. return err;
  406. }
  407. int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
  408. struct net_device *dev,
  409. struct ieee80211_channel *chan,
  410. const u8 *bssid, const u8 *prev_bssid,
  411. const u8 *ssid, int ssid_len,
  412. const u8 *ie, int ie_len, bool use_mfp,
  413. struct cfg80211_crypto_settings *crypt)
  414. {
  415. struct wireless_dev *wdev = dev->ieee80211_ptr;
  416. struct cfg80211_assoc_request req;
  417. struct cfg80211_internal_bss *bss;
  418. int i, err, slot = -1;
  419. bool was_connected = false;
  420. ASSERT_WDEV_LOCK(wdev);
  421. memset(&req, 0, sizeof(req));
  422. if (wdev->current_bss && prev_bssid &&
  423. memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) {
  424. /*
  425. * Trying to reassociate: Allow this to proceed and let the old
  426. * association to be dropped when the new one is completed.
  427. */
  428. if (wdev->sme_state == CFG80211_SME_CONNECTED) {
  429. was_connected = true;
  430. wdev->sme_state = CFG80211_SME_CONNECTING;
  431. }
  432. } else if (wdev->current_bss)
  433. return -EALREADY;
  434. req.ie = ie;
  435. req.ie_len = ie_len;
  436. memcpy(&req.crypto, crypt, sizeof(req.crypto));
  437. req.use_mfp = use_mfp;
  438. req.prev_bssid = prev_bssid;
  439. req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
  440. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  441. if (!req.bss) {
  442. if (was_connected)
  443. wdev->sme_state = CFG80211_SME_CONNECTED;
  444. return -ENOENT;
  445. }
  446. bss = bss_from_pub(req.bss);
  447. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  448. if (bss == wdev->auth_bsses[i]) {
  449. slot = i;
  450. break;
  451. }
  452. }
  453. if (slot < 0) {
  454. err = -ENOTCONN;
  455. goto out;
  456. }
  457. err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
  458. out:
  459. if (err && was_connected)
  460. wdev->sme_state = CFG80211_SME_CONNECTED;
  461. /* still a reference in wdev->auth_bsses[slot] */
  462. cfg80211_put_bss(req.bss);
  463. return err;
  464. }
  465. int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
  466. struct net_device *dev,
  467. struct ieee80211_channel *chan,
  468. const u8 *bssid, const u8 *prev_bssid,
  469. const u8 *ssid, int ssid_len,
  470. const u8 *ie, int ie_len, bool use_mfp,
  471. struct cfg80211_crypto_settings *crypt)
  472. {
  473. struct wireless_dev *wdev = dev->ieee80211_ptr;
  474. int err;
  475. wdev_lock(wdev);
  476. err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
  477. ssid, ssid_len, ie, ie_len, use_mfp, crypt);
  478. wdev_unlock(wdev);
  479. return err;
  480. }
  481. int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
  482. struct net_device *dev, const u8 *bssid,
  483. const u8 *ie, int ie_len, u16 reason,
  484. bool local_state_change)
  485. {
  486. struct wireless_dev *wdev = dev->ieee80211_ptr;
  487. struct cfg80211_deauth_request req;
  488. int i;
  489. ASSERT_WDEV_LOCK(wdev);
  490. memset(&req, 0, sizeof(req));
  491. req.reason_code = reason;
  492. req.local_state_change = local_state_change;
  493. req.ie = ie;
  494. req.ie_len = ie_len;
  495. if (wdev->current_bss &&
  496. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  497. req.bss = &wdev->current_bss->pub;
  498. } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
  499. if (wdev->auth_bsses[i] &&
  500. memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
  501. req.bss = &wdev->auth_bsses[i]->pub;
  502. break;
  503. }
  504. if (wdev->authtry_bsses[i] &&
  505. memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
  506. req.bss = &wdev->authtry_bsses[i]->pub;
  507. break;
  508. }
  509. }
  510. if (!req.bss)
  511. return -ENOTCONN;
  512. return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  513. }
  514. int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
  515. struct net_device *dev, const u8 *bssid,
  516. const u8 *ie, int ie_len, u16 reason,
  517. bool local_state_change)
  518. {
  519. struct wireless_dev *wdev = dev->ieee80211_ptr;
  520. int err;
  521. wdev_lock(wdev);
  522. err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
  523. local_state_change);
  524. wdev_unlock(wdev);
  525. return err;
  526. }
  527. static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
  528. struct net_device *dev, const u8 *bssid,
  529. const u8 *ie, int ie_len, u16 reason,
  530. bool local_state_change)
  531. {
  532. struct wireless_dev *wdev = dev->ieee80211_ptr;
  533. struct cfg80211_disassoc_request req;
  534. ASSERT_WDEV_LOCK(wdev);
  535. if (wdev->sme_state != CFG80211_SME_CONNECTED)
  536. return -ENOTCONN;
  537. if (WARN_ON(!wdev->current_bss))
  538. return -ENOTCONN;
  539. memset(&req, 0, sizeof(req));
  540. req.reason_code = reason;
  541. req.local_state_change = local_state_change;
  542. req.ie = ie;
  543. req.ie_len = ie_len;
  544. if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
  545. req.bss = &wdev->current_bss->pub;
  546. else
  547. return -ENOTCONN;
  548. return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev);
  549. }
  550. int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
  551. struct net_device *dev, const u8 *bssid,
  552. const u8 *ie, int ie_len, u16 reason,
  553. bool local_state_change)
  554. {
  555. struct wireless_dev *wdev = dev->ieee80211_ptr;
  556. int err;
  557. wdev_lock(wdev);
  558. err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
  559. local_state_change);
  560. wdev_unlock(wdev);
  561. return err;
  562. }
  563. void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
  564. struct net_device *dev)
  565. {
  566. struct wireless_dev *wdev = dev->ieee80211_ptr;
  567. struct cfg80211_deauth_request req;
  568. int i;
  569. ASSERT_WDEV_LOCK(wdev);
  570. if (!rdev->ops->deauth)
  571. return;
  572. memset(&req, 0, sizeof(req));
  573. req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
  574. req.ie = NULL;
  575. req.ie_len = 0;
  576. if (wdev->current_bss) {
  577. req.bss = &wdev->current_bss->pub;
  578. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  579. if (wdev->current_bss) {
  580. cfg80211_unhold_bss(wdev->current_bss);
  581. cfg80211_put_bss(&wdev->current_bss->pub);
  582. wdev->current_bss = NULL;
  583. }
  584. }
  585. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  586. if (wdev->auth_bsses[i]) {
  587. req.bss = &wdev->auth_bsses[i]->pub;
  588. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  589. if (wdev->auth_bsses[i]) {
  590. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  591. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  592. wdev->auth_bsses[i] = NULL;
  593. }
  594. }
  595. if (wdev->authtry_bsses[i]) {
  596. req.bss = &wdev->authtry_bsses[i]->pub;
  597. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  598. if (wdev->authtry_bsses[i]) {
  599. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  600. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  601. wdev->authtry_bsses[i] = NULL;
  602. }
  603. }
  604. }
  605. }
  606. void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
  607. struct ieee80211_channel *chan,
  608. enum nl80211_channel_type channel_type,
  609. unsigned int duration, gfp_t gfp)
  610. {
  611. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  612. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  613. nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type,
  614. duration, gfp);
  615. }
  616. EXPORT_SYMBOL(cfg80211_ready_on_channel);
  617. void cfg80211_remain_on_channel_expired(struct net_device *dev,
  618. u64 cookie,
  619. struct ieee80211_channel *chan,
  620. enum nl80211_channel_type channel_type,
  621. gfp_t gfp)
  622. {
  623. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  624. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  625. nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan,
  626. channel_type, gfp);
  627. }
  628. EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
  629. void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
  630. struct station_info *sinfo, gfp_t gfp)
  631. {
  632. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  633. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  634. nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
  635. }
  636. EXPORT_SYMBOL(cfg80211_new_sta);
  637. struct cfg80211_action_registration {
  638. struct list_head list;
  639. u32 nlpid;
  640. int match_len;
  641. u8 match[];
  642. };
  643. int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
  644. const u8 *match_data, int match_len)
  645. {
  646. struct cfg80211_action_registration *reg, *nreg;
  647. int err = 0;
  648. nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
  649. if (!nreg)
  650. return -ENOMEM;
  651. spin_lock_bh(&wdev->action_registrations_lock);
  652. list_for_each_entry(reg, &wdev->action_registrations, list) {
  653. int mlen = min(match_len, reg->match_len);
  654. if (memcmp(reg->match, match_data, mlen) == 0) {
  655. err = -EALREADY;
  656. break;
  657. }
  658. }
  659. if (err) {
  660. kfree(nreg);
  661. goto out;
  662. }
  663. memcpy(nreg->match, match_data, match_len);
  664. nreg->match_len = match_len;
  665. nreg->nlpid = snd_pid;
  666. list_add(&nreg->list, &wdev->action_registrations);
  667. out:
  668. spin_unlock_bh(&wdev->action_registrations_lock);
  669. return err;
  670. }
  671. void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid)
  672. {
  673. struct cfg80211_action_registration *reg, *tmp;
  674. spin_lock_bh(&wdev->action_registrations_lock);
  675. list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
  676. if (reg->nlpid == nlpid) {
  677. list_del(&reg->list);
  678. kfree(reg);
  679. }
  680. }
  681. spin_unlock_bh(&wdev->action_registrations_lock);
  682. }
  683. void cfg80211_mlme_purge_actions(struct wireless_dev *wdev)
  684. {
  685. struct cfg80211_action_registration *reg, *tmp;
  686. spin_lock_bh(&wdev->action_registrations_lock);
  687. list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
  688. list_del(&reg->list);
  689. kfree(reg);
  690. }
  691. spin_unlock_bh(&wdev->action_registrations_lock);
  692. }
  693. int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
  694. struct net_device *dev,
  695. struct ieee80211_channel *chan,
  696. enum nl80211_channel_type channel_type,
  697. bool channel_type_valid,
  698. const u8 *buf, size_t len, u64 *cookie)
  699. {
  700. struct wireless_dev *wdev = dev->ieee80211_ptr;
  701. const struct ieee80211_mgmt *mgmt;
  702. if (rdev->ops->action == NULL)
  703. return -EOPNOTSUPP;
  704. if (len < 24 + 1)
  705. return -EINVAL;
  706. mgmt = (const struct ieee80211_mgmt *) buf;
  707. if (!ieee80211_is_action(mgmt->frame_control))
  708. return -EINVAL;
  709. if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
  710. /* Verify that we are associated with the destination AP */
  711. wdev_lock(wdev);
  712. if (!wdev->current_bss ||
  713. memcmp(wdev->current_bss->pub.bssid, mgmt->bssid,
  714. ETH_ALEN) != 0 ||
  715. (wdev->iftype == NL80211_IFTYPE_STATION &&
  716. memcmp(wdev->current_bss->pub.bssid, mgmt->da,
  717. ETH_ALEN) != 0)) {
  718. wdev_unlock(wdev);
  719. return -ENOTCONN;
  720. }
  721. wdev_unlock(wdev);
  722. }
  723. if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
  724. return -EINVAL;
  725. /* Transmit the Action frame as requested by user space */
  726. return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type,
  727. channel_type_valid, buf, len, cookie);
  728. }
  729. bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
  730. size_t len, gfp_t gfp)
  731. {
  732. struct wireless_dev *wdev = dev->ieee80211_ptr;
  733. struct wiphy *wiphy = wdev->wiphy;
  734. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  735. struct cfg80211_action_registration *reg;
  736. const u8 *action_data;
  737. int action_data_len;
  738. bool result = false;
  739. /* frame length - min size excluding category */
  740. action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1);
  741. /* action data starts with category */
  742. action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1;
  743. spin_lock_bh(&wdev->action_registrations_lock);
  744. list_for_each_entry(reg, &wdev->action_registrations, list) {
  745. if (reg->match_len > action_data_len)
  746. continue;
  747. if (memcmp(reg->match, action_data, reg->match_len))
  748. continue;
  749. /* found match! */
  750. /* Indicate the received Action frame to user space */
  751. if (nl80211_send_action(rdev, dev, reg->nlpid, freq,
  752. buf, len, gfp))
  753. continue;
  754. result = true;
  755. break;
  756. }
  757. spin_unlock_bh(&wdev->action_registrations_lock);
  758. return result;
  759. }
  760. EXPORT_SYMBOL(cfg80211_rx_action);
  761. void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
  762. const u8 *buf, size_t len, bool ack, gfp_t gfp)
  763. {
  764. struct wireless_dev *wdev = dev->ieee80211_ptr;
  765. struct wiphy *wiphy = wdev->wiphy;
  766. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  767. /* Indicate TX status of the Action frame to user space */
  768. nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
  769. }
  770. EXPORT_SYMBOL(cfg80211_action_tx_status);
  771. void cfg80211_cqm_rssi_notify(struct net_device *dev,
  772. enum nl80211_cqm_rssi_threshold_event rssi_event,
  773. gfp_t gfp)
  774. {
  775. struct wireless_dev *wdev = dev->ieee80211_ptr;
  776. struct wiphy *wiphy = wdev->wiphy;
  777. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  778. /* Indicate roaming trigger event to user space */
  779. nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp);
  780. }
  781. EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);