mlme.c 24 KB

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