mlme.c 23 KB

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