mlme.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  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. {
  326. struct wireless_dev *wdev = dev->ieee80211_ptr;
  327. struct cfg80211_auth_request req;
  328. struct cfg80211_internal_bss *bss;
  329. int i, err, slot = -1, nfree = 0;
  330. ASSERT_WDEV_LOCK(wdev);
  331. if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
  332. if (!key || !key_len || key_idx < 0 || key_idx > 4)
  333. return -EINVAL;
  334. if (wdev->current_bss &&
  335. memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
  336. return -EALREADY;
  337. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  338. if (wdev->authtry_bsses[i] &&
  339. memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid,
  340. ETH_ALEN) == 0)
  341. return -EALREADY;
  342. if (wdev->auth_bsses[i] &&
  343. memcmp(bssid, wdev->auth_bsses[i]->pub.bssid,
  344. ETH_ALEN) == 0)
  345. return -EALREADY;
  346. }
  347. memset(&req, 0, sizeof(req));
  348. req.ie = ie;
  349. req.ie_len = ie_len;
  350. req.auth_type = auth_type;
  351. req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
  352. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  353. req.key = key;
  354. req.key_len = key_len;
  355. req.key_idx = key_idx;
  356. if (!req.bss)
  357. return -ENOENT;
  358. bss = bss_from_pub(req.bss);
  359. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  360. if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) {
  361. slot = i;
  362. nfree++;
  363. }
  364. }
  365. /* we need one free slot for disassoc and one for this auth */
  366. if (nfree < 2) {
  367. err = -ENOSPC;
  368. goto out;
  369. }
  370. wdev->authtry_bsses[slot] = bss;
  371. cfg80211_hold_bss(bss);
  372. err = rdev->ops->auth(&rdev->wiphy, dev, &req);
  373. if (err) {
  374. wdev->authtry_bsses[slot] = NULL;
  375. cfg80211_unhold_bss(bss);
  376. }
  377. out:
  378. if (err)
  379. cfg80211_put_bss(req.bss);
  380. return err;
  381. }
  382. int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
  383. struct net_device *dev, struct ieee80211_channel *chan,
  384. enum nl80211_auth_type auth_type, const u8 *bssid,
  385. const u8 *ssid, int ssid_len,
  386. const u8 *ie, int ie_len,
  387. const u8 *key, int key_len, int key_idx)
  388. {
  389. int err;
  390. wdev_lock(dev->ieee80211_ptr);
  391. err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
  392. ssid, ssid_len, ie, ie_len,
  393. key, key_len, key_idx);
  394. wdev_unlock(dev->ieee80211_ptr);
  395. return err;
  396. }
  397. int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
  398. struct net_device *dev,
  399. struct ieee80211_channel *chan,
  400. const u8 *bssid, const u8 *prev_bssid,
  401. const u8 *ssid, int ssid_len,
  402. const u8 *ie, int ie_len, bool use_mfp,
  403. struct cfg80211_crypto_settings *crypt)
  404. {
  405. struct wireless_dev *wdev = dev->ieee80211_ptr;
  406. struct cfg80211_assoc_request req;
  407. struct cfg80211_internal_bss *bss;
  408. int i, err, slot = -1;
  409. bool was_connected = false;
  410. ASSERT_WDEV_LOCK(wdev);
  411. memset(&req, 0, sizeof(req));
  412. if (wdev->current_bss && prev_bssid &&
  413. memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) {
  414. /*
  415. * Trying to reassociate: Allow this to proceed and let the old
  416. * association to be dropped when the new one is completed.
  417. */
  418. if (wdev->sme_state == CFG80211_SME_CONNECTED) {
  419. was_connected = true;
  420. wdev->sme_state = CFG80211_SME_CONNECTING;
  421. }
  422. } else if (wdev->current_bss)
  423. return -EALREADY;
  424. req.ie = ie;
  425. req.ie_len = ie_len;
  426. memcpy(&req.crypto, crypt, sizeof(req.crypto));
  427. req.use_mfp = use_mfp;
  428. req.prev_bssid = prev_bssid;
  429. req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
  430. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  431. if (!req.bss) {
  432. if (was_connected)
  433. wdev->sme_state = CFG80211_SME_CONNECTED;
  434. return -ENOENT;
  435. }
  436. bss = bss_from_pub(req.bss);
  437. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  438. if (bss == wdev->auth_bsses[i]) {
  439. slot = i;
  440. break;
  441. }
  442. }
  443. if (slot < 0) {
  444. err = -ENOTCONN;
  445. goto out;
  446. }
  447. err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
  448. out:
  449. if (err && was_connected)
  450. wdev->sme_state = CFG80211_SME_CONNECTED;
  451. /* still a reference in wdev->auth_bsses[slot] */
  452. cfg80211_put_bss(req.bss);
  453. return err;
  454. }
  455. int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
  456. struct net_device *dev,
  457. struct ieee80211_channel *chan,
  458. const u8 *bssid, const u8 *prev_bssid,
  459. const u8 *ssid, int ssid_len,
  460. const u8 *ie, int ie_len, bool use_mfp,
  461. struct cfg80211_crypto_settings *crypt)
  462. {
  463. struct wireless_dev *wdev = dev->ieee80211_ptr;
  464. int err;
  465. wdev_lock(wdev);
  466. err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
  467. ssid, ssid_len, ie, ie_len, use_mfp, crypt);
  468. wdev_unlock(wdev);
  469. return err;
  470. }
  471. int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
  472. struct net_device *dev, const u8 *bssid,
  473. const u8 *ie, int ie_len, u16 reason)
  474. {
  475. struct wireless_dev *wdev = dev->ieee80211_ptr;
  476. struct cfg80211_deauth_request req;
  477. int i;
  478. ASSERT_WDEV_LOCK(wdev);
  479. memset(&req, 0, sizeof(req));
  480. req.reason_code = reason;
  481. req.ie = ie;
  482. req.ie_len = ie_len;
  483. if (wdev->current_bss &&
  484. memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
  485. req.bss = &wdev->current_bss->pub;
  486. } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
  487. if (wdev->auth_bsses[i] &&
  488. memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
  489. req.bss = &wdev->auth_bsses[i]->pub;
  490. break;
  491. }
  492. if (wdev->authtry_bsses[i] &&
  493. memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
  494. req.bss = &wdev->authtry_bsses[i]->pub;
  495. break;
  496. }
  497. }
  498. if (!req.bss)
  499. return -ENOTCONN;
  500. return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  501. }
  502. int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
  503. struct net_device *dev, const u8 *bssid,
  504. const u8 *ie, int ie_len, u16 reason)
  505. {
  506. struct wireless_dev *wdev = dev->ieee80211_ptr;
  507. int err;
  508. wdev_lock(wdev);
  509. err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason);
  510. wdev_unlock(wdev);
  511. return err;
  512. }
  513. static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
  514. struct net_device *dev, const u8 *bssid,
  515. const u8 *ie, int ie_len, u16 reason)
  516. {
  517. struct wireless_dev *wdev = dev->ieee80211_ptr;
  518. struct cfg80211_disassoc_request req;
  519. ASSERT_WDEV_LOCK(wdev);
  520. if (wdev->sme_state != CFG80211_SME_CONNECTED)
  521. return -ENOTCONN;
  522. if (WARN_ON(!wdev->current_bss))
  523. return -ENOTCONN;
  524. memset(&req, 0, sizeof(req));
  525. req.reason_code = reason;
  526. req.ie = ie;
  527. req.ie_len = ie_len;
  528. if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
  529. req.bss = &wdev->current_bss->pub;
  530. else
  531. return -ENOTCONN;
  532. return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev);
  533. }
  534. int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
  535. struct net_device *dev, const u8 *bssid,
  536. const u8 *ie, int ie_len, u16 reason)
  537. {
  538. struct wireless_dev *wdev = dev->ieee80211_ptr;
  539. int err;
  540. wdev_lock(wdev);
  541. err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason);
  542. wdev_unlock(wdev);
  543. return err;
  544. }
  545. void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
  546. struct net_device *dev)
  547. {
  548. struct wireless_dev *wdev = dev->ieee80211_ptr;
  549. struct cfg80211_deauth_request req;
  550. int i;
  551. ASSERT_WDEV_LOCK(wdev);
  552. if (!rdev->ops->deauth)
  553. return;
  554. memset(&req, 0, sizeof(req));
  555. req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
  556. req.ie = NULL;
  557. req.ie_len = 0;
  558. if (wdev->current_bss) {
  559. req.bss = &wdev->current_bss->pub;
  560. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  561. if (wdev->current_bss) {
  562. cfg80211_unhold_bss(wdev->current_bss);
  563. cfg80211_put_bss(&wdev->current_bss->pub);
  564. wdev->current_bss = NULL;
  565. }
  566. }
  567. for (i = 0; i < MAX_AUTH_BSSES; i++) {
  568. if (wdev->auth_bsses[i]) {
  569. req.bss = &wdev->auth_bsses[i]->pub;
  570. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  571. if (wdev->auth_bsses[i]) {
  572. cfg80211_unhold_bss(wdev->auth_bsses[i]);
  573. cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
  574. wdev->auth_bsses[i] = NULL;
  575. }
  576. }
  577. if (wdev->authtry_bsses[i]) {
  578. req.bss = &wdev->authtry_bsses[i]->pub;
  579. rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
  580. if (wdev->authtry_bsses[i]) {
  581. cfg80211_unhold_bss(wdev->authtry_bsses[i]);
  582. cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
  583. wdev->authtry_bsses[i] = NULL;
  584. }
  585. }
  586. }
  587. }
  588. void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
  589. struct ieee80211_channel *chan,
  590. enum nl80211_channel_type channel_type,
  591. unsigned int duration, gfp_t gfp)
  592. {
  593. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  594. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  595. nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type,
  596. duration, gfp);
  597. }
  598. EXPORT_SYMBOL(cfg80211_ready_on_channel);
  599. void cfg80211_remain_on_channel_expired(struct net_device *dev,
  600. u64 cookie,
  601. struct ieee80211_channel *chan,
  602. enum nl80211_channel_type channel_type,
  603. gfp_t gfp)
  604. {
  605. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  606. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  607. nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan,
  608. channel_type, gfp);
  609. }
  610. EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
  611. void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
  612. struct station_info *sinfo, gfp_t gfp)
  613. {
  614. struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  615. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  616. nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
  617. }
  618. EXPORT_SYMBOL(cfg80211_new_sta);
  619. struct cfg80211_action_registration {
  620. struct list_head list;
  621. u32 nlpid;
  622. int match_len;
  623. u8 match[];
  624. };
  625. int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
  626. const u8 *match_data, int match_len)
  627. {
  628. struct cfg80211_action_registration *reg, *nreg;
  629. int err = 0;
  630. nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
  631. if (!nreg)
  632. return -ENOMEM;
  633. spin_lock_bh(&wdev->action_registrations_lock);
  634. list_for_each_entry(reg, &wdev->action_registrations, list) {
  635. int mlen = min(match_len, reg->match_len);
  636. if (memcmp(reg->match, match_data, mlen) == 0) {
  637. err = -EALREADY;
  638. break;
  639. }
  640. }
  641. if (err) {
  642. kfree(nreg);
  643. goto out;
  644. }
  645. memcpy(nreg->match, match_data, match_len);
  646. nreg->match_len = match_len;
  647. nreg->nlpid = snd_pid;
  648. list_add(&nreg->list, &wdev->action_registrations);
  649. out:
  650. spin_unlock_bh(&wdev->action_registrations_lock);
  651. return err;
  652. }
  653. void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid)
  654. {
  655. struct cfg80211_action_registration *reg, *tmp;
  656. spin_lock_bh(&wdev->action_registrations_lock);
  657. list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
  658. if (reg->nlpid == nlpid) {
  659. list_del(&reg->list);
  660. kfree(reg);
  661. }
  662. }
  663. spin_unlock_bh(&wdev->action_registrations_lock);
  664. }
  665. void cfg80211_mlme_purge_actions(struct wireless_dev *wdev)
  666. {
  667. struct cfg80211_action_registration *reg, *tmp;
  668. spin_lock_bh(&wdev->action_registrations_lock);
  669. list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
  670. list_del(&reg->list);
  671. kfree(reg);
  672. }
  673. spin_unlock_bh(&wdev->action_registrations_lock);
  674. }
  675. int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
  676. struct net_device *dev,
  677. struct ieee80211_channel *chan,
  678. enum nl80211_channel_type channel_type,
  679. const u8 *buf, size_t len, u64 *cookie)
  680. {
  681. struct wireless_dev *wdev = dev->ieee80211_ptr;
  682. const struct ieee80211_mgmt *mgmt;
  683. if (rdev->ops->action == NULL)
  684. return -EOPNOTSUPP;
  685. if (len < 24 + 1)
  686. return -EINVAL;
  687. mgmt = (const struct ieee80211_mgmt *) buf;
  688. if (!ieee80211_is_action(mgmt->frame_control))
  689. return -EINVAL;
  690. if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
  691. /* Verify that we are associated with the destination AP */
  692. if (!wdev->current_bss ||
  693. memcmp(wdev->current_bss->pub.bssid, mgmt->bssid,
  694. ETH_ALEN) != 0 ||
  695. memcmp(wdev->current_bss->pub.bssid, mgmt->da,
  696. ETH_ALEN) != 0)
  697. return -ENOTCONN;
  698. }
  699. if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
  700. return -EINVAL;
  701. /* Transmit the Action frame as requested by user space */
  702. return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type,
  703. buf, len, cookie);
  704. }
  705. bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
  706. size_t len, gfp_t gfp)
  707. {
  708. struct wireless_dev *wdev = dev->ieee80211_ptr;
  709. struct wiphy *wiphy = wdev->wiphy;
  710. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  711. struct cfg80211_action_registration *reg;
  712. const u8 *action_data;
  713. int action_data_len;
  714. bool result = false;
  715. /* frame length - min size excluding category */
  716. action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1);
  717. /* action data starts with category */
  718. action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1;
  719. spin_lock_bh(&wdev->action_registrations_lock);
  720. list_for_each_entry(reg, &wdev->action_registrations, list) {
  721. if (reg->match_len > action_data_len)
  722. continue;
  723. if (memcmp(reg->match, action_data, reg->match_len))
  724. continue;
  725. /* found match! */
  726. /* Indicate the received Action frame to user space */
  727. if (nl80211_send_action(rdev, dev, reg->nlpid, freq,
  728. buf, len, gfp))
  729. continue;
  730. result = true;
  731. break;
  732. }
  733. spin_unlock_bh(&wdev->action_registrations_lock);
  734. return result;
  735. }
  736. EXPORT_SYMBOL(cfg80211_rx_action);
  737. void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
  738. const u8 *buf, size_t len, bool ack, gfp_t gfp)
  739. {
  740. struct wireless_dev *wdev = dev->ieee80211_ptr;
  741. struct wiphy *wiphy = wdev->wiphy;
  742. struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  743. /* Indicate TX status of the Action frame to user space */
  744. nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
  745. }
  746. EXPORT_SYMBOL(cfg80211_action_tx_status);