assoc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /* Copyright (C) 2006, Red Hat, Inc. */
  2. #include <linux/bitops.h>
  3. #include <net/ieee80211.h>
  4. #include "assoc.h"
  5. #include "join.h"
  6. #include "decl.h"
  7. #include "hostcmd.h"
  8. #include "host.h"
  9. static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  10. static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  11. /* From ieee80211_module.c */
  12. static const char *libertas_escape_essid(const char *essid, u8 essid_len)
  13. {
  14. static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
  15. const char *s = essid;
  16. char *d = escaped;
  17. if (ieee80211_is_empty_essid(essid, essid_len))
  18. return "";
  19. essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
  20. while (essid_len--) {
  21. if (*s == '\0') {
  22. *d++ = '\\';
  23. *d++ = '0';
  24. s++;
  25. } else {
  26. *d++ = *s++;
  27. }
  28. }
  29. *d = '\0';
  30. return escaped;
  31. }
  32. static void print_assoc_req(const char * extra, struct assoc_request * assoc_req)
  33. {
  34. lbs_deb_assoc(
  35. "#### Association Request: %s\n"
  36. " flags: 0x%08lX\n"
  37. " SSID: '%s'\n"
  38. " channel: %d\n"
  39. " band: %d\n"
  40. " mode: %d\n"
  41. " BSSID: " MAC_FMT "\n"
  42. " WPA: %d\n"
  43. " WPA2: %d\n"
  44. " WEP status: %d\n"
  45. " auth: %d\n"
  46. " auth_alg: %d\n"
  47. " encmode: %d\n",
  48. extra, assoc_req->flags,
  49. libertas_escape_essid(assoc_req->ssid.ssid, assoc_req->ssid.ssidlength),
  50. assoc_req->channel, assoc_req->band, assoc_req->mode,
  51. MAC_ARG(assoc_req->bssid), assoc_req->secinfo.WPAenabled,
  52. assoc_req->secinfo.WPA2enabled, assoc_req->secinfo.WEPstatus,
  53. assoc_req->secinfo.authmode, assoc_req->secinfo.auth1xalg,
  54. assoc_req->secinfo.Encryptionmode);
  55. }
  56. static int assoc_helper_essid(wlan_private *priv,
  57. struct assoc_request * assoc_req)
  58. {
  59. wlan_adapter *adapter = priv->adapter;
  60. int ret = 0;
  61. struct bss_descriptor * bss;
  62. lbs_deb_enter(LBS_DEB_ASSOC);
  63. /* FIXME: take channel into account when picking SSIDs if a channel
  64. * is set.
  65. */
  66. lbs_deb_assoc("New SSID requested: %s\n", assoc_req->ssid.ssid);
  67. if (assoc_req->mode == IW_MODE_INFRA) {
  68. if (adapter->prescan) {
  69. libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0);
  70. }
  71. bss = libertas_find_SSID_in_list(adapter, &assoc_req->ssid,
  72. NULL, IW_MODE_INFRA);
  73. if (bss != NULL) {
  74. lbs_deb_assoc("SSID found in scan list, associating\n");
  75. memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
  76. ret = wlan_associate(priv, assoc_req);
  77. } else {
  78. lbs_deb_assoc("SSID '%s' not found; cannot associate\n",
  79. assoc_req->ssid.ssid);
  80. }
  81. } else if (assoc_req->mode == IW_MODE_ADHOC) {
  82. /* Scan for the network, do not save previous results. Stale
  83. * scan data will cause us to join a non-existant adhoc network
  84. */
  85. libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1);
  86. /* Search for the requested SSID in the scan table */
  87. bss = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL,
  88. IW_MODE_ADHOC);
  89. if (bss != NULL) {
  90. lbs_deb_assoc("SSID found joining\n");
  91. memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
  92. libertas_join_adhoc_network(priv, assoc_req);
  93. } else {
  94. /* else send START command */
  95. lbs_deb_assoc("SSID not found in list, so creating adhoc"
  96. " with SSID '%s'\n", assoc_req->ssid.ssid);
  97. memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
  98. sizeof(struct WLAN_802_11_SSID));
  99. libertas_start_adhoc_network(priv, assoc_req);
  100. }
  101. }
  102. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  103. return ret;
  104. }
  105. static int assoc_helper_bssid(wlan_private *priv,
  106. struct assoc_request * assoc_req)
  107. {
  108. wlan_adapter *adapter = priv->adapter;
  109. int ret = 0;
  110. struct bss_descriptor * bss;
  111. lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID" MAC_FMT "\n",
  112. MAC_ARG(assoc_req->bssid));
  113. /* Search for index position in list for requested MAC */
  114. bss = libertas_find_BSSID_in_list(adapter, assoc_req->bssid,
  115. assoc_req->mode);
  116. if (bss == NULL) {
  117. lbs_deb_assoc("ASSOC: WAP: BSSID " MAC_FMT " not found, "
  118. "cannot associate.\n", MAC_ARG(assoc_req->bssid));
  119. goto out;
  120. }
  121. memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
  122. if (assoc_req->mode == IW_MODE_INFRA) {
  123. ret = wlan_associate(priv, assoc_req);
  124. lbs_deb_assoc("ASSOC: wlan_associate(bssid) returned %d\n", ret);
  125. } else if (assoc_req->mode == IW_MODE_ADHOC) {
  126. libertas_join_adhoc_network(priv, assoc_req);
  127. }
  128. out:
  129. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  130. return ret;
  131. }
  132. static int assoc_helper_associate(wlan_private *priv,
  133. struct assoc_request * assoc_req)
  134. {
  135. int ret = 0, done = 0;
  136. /* If we're given and 'any' BSSID, try associating based on SSID */
  137. if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
  138. if (memcmp(bssid_any, assoc_req->bssid, ETH_ALEN)
  139. && memcmp(bssid_off, assoc_req->bssid, ETH_ALEN)) {
  140. ret = assoc_helper_bssid(priv, assoc_req);
  141. done = 1;
  142. if (ret) {
  143. lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
  144. }
  145. }
  146. }
  147. if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
  148. ret = assoc_helper_essid(priv, assoc_req);
  149. if (ret) {
  150. lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
  151. }
  152. }
  153. return ret;
  154. }
  155. static int assoc_helper_mode(wlan_private *priv,
  156. struct assoc_request * assoc_req)
  157. {
  158. wlan_adapter *adapter = priv->adapter;
  159. int ret = 0;
  160. lbs_deb_enter(LBS_DEB_ASSOC);
  161. if (assoc_req->mode == adapter->mode)
  162. goto done;
  163. if (assoc_req->mode == IW_MODE_INFRA) {
  164. if (adapter->psstate != PS_STATE_FULL_POWER)
  165. libertas_ps_wakeup(priv, cmd_option_waitforrsp);
  166. adapter->psmode = wlan802_11powermodecam;
  167. }
  168. adapter->mode = assoc_req->mode;
  169. ret = libertas_prepare_and_send_command(priv,
  170. cmd_802_11_snmp_mib,
  171. 0, cmd_option_waitforrsp,
  172. OID_802_11_INFRASTRUCTURE_MODE,
  173. (void *) (size_t) assoc_req->mode);
  174. done:
  175. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  176. return ret;
  177. }
  178. static int update_channel(wlan_private * priv)
  179. {
  180. /* the channel in f/w could be out of sync, get the current channel */
  181. return libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
  182. cmd_opt_802_11_rf_channel_get,
  183. cmd_option_waitforrsp, 0, NULL);
  184. }
  185. static int assoc_helper_channel(wlan_private *priv,
  186. struct assoc_request * assoc_req)
  187. {
  188. wlan_adapter *adapter = priv->adapter;
  189. int ret = 0;
  190. lbs_deb_enter(LBS_DEB_ASSOC);
  191. ret = update_channel(priv);
  192. if (ret < 0) {
  193. lbs_deb_assoc("ASSOC: channel: error getting channel.");
  194. }
  195. if (assoc_req->channel == adapter->curbssparams.channel)
  196. goto done;
  197. lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
  198. adapter->curbssparams.channel, assoc_req->channel);
  199. ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
  200. cmd_opt_802_11_rf_channel_set,
  201. cmd_option_waitforrsp, 0, &assoc_req->channel);
  202. if (ret < 0) {
  203. lbs_deb_assoc("ASSOC: channel: error setting channel.");
  204. }
  205. ret = update_channel(priv);
  206. if (ret < 0) {
  207. lbs_deb_assoc("ASSOC: channel: error getting channel.");
  208. }
  209. if (assoc_req->channel != adapter->curbssparams.channel) {
  210. lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
  211. assoc_req->channel);
  212. goto done;
  213. }
  214. if ( assoc_req->secinfo.wep_enabled
  215. && (assoc_req->wep_keys[0].len
  216. || assoc_req->wep_keys[1].len
  217. || assoc_req->wep_keys[2].len
  218. || assoc_req->wep_keys[3].len)) {
  219. /* Make sure WEP keys are re-sent to firmware */
  220. set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
  221. }
  222. /* Must restart/rejoin adhoc networks after channel change */
  223. set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
  224. done:
  225. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  226. return ret;
  227. }
  228. static int assoc_helper_wep_keys(wlan_private *priv,
  229. struct assoc_request * assoc_req)
  230. {
  231. wlan_adapter *adapter = priv->adapter;
  232. int i;
  233. int ret = 0;
  234. lbs_deb_enter(LBS_DEB_ASSOC);
  235. /* Set or remove WEP keys */
  236. if ( assoc_req->wep_keys[0].len
  237. || assoc_req->wep_keys[1].len
  238. || assoc_req->wep_keys[2].len
  239. || assoc_req->wep_keys[3].len) {
  240. ret = libertas_prepare_and_send_command(priv,
  241. cmd_802_11_set_wep,
  242. cmd_act_add,
  243. cmd_option_waitforrsp,
  244. 0, assoc_req);
  245. } else {
  246. ret = libertas_prepare_and_send_command(priv,
  247. cmd_802_11_set_wep,
  248. cmd_act_remove,
  249. cmd_option_waitforrsp,
  250. 0, NULL);
  251. }
  252. if (ret)
  253. goto out;
  254. /* enable/disable the MAC's WEP packet filter */
  255. if (assoc_req->secinfo.wep_enabled)
  256. adapter->currentpacketfilter |= cmd_act_mac_wep_enable;
  257. else
  258. adapter->currentpacketfilter &= ~cmd_act_mac_wep_enable;
  259. ret = libertas_set_mac_packet_filter(priv);
  260. if (ret)
  261. goto out;
  262. mutex_lock(&adapter->lock);
  263. /* Copy WEP keys into adapter wep key fields */
  264. for (i = 0; i < 4; i++) {
  265. memcpy(&adapter->wep_keys[i], &assoc_req->wep_keys[i],
  266. sizeof(struct WLAN_802_11_KEY));
  267. }
  268. adapter->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
  269. mutex_unlock(&adapter->lock);
  270. out:
  271. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  272. return ret;
  273. }
  274. static int assoc_helper_secinfo(wlan_private *priv,
  275. struct assoc_request * assoc_req)
  276. {
  277. wlan_adapter *adapter = priv->adapter;
  278. int ret = 0;
  279. lbs_deb_enter(LBS_DEB_ASSOC);
  280. memcpy(&adapter->secinfo, &assoc_req->secinfo,
  281. sizeof(struct wlan_802_11_security));
  282. ret = libertas_set_mac_packet_filter(priv);
  283. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  284. return ret;
  285. }
  286. static int assoc_helper_wpa_keys(wlan_private *priv,
  287. struct assoc_request * assoc_req)
  288. {
  289. int ret = 0;
  290. lbs_deb_enter(LBS_DEB_ASSOC);
  291. /* enable/Disable RSN */
  292. ret = libertas_prepare_and_send_command(priv,
  293. cmd_802_11_enable_rsn,
  294. cmd_act_set,
  295. cmd_option_waitforrsp,
  296. 0, assoc_req);
  297. if (ret)
  298. goto out;
  299. ret = libertas_prepare_and_send_command(priv,
  300. cmd_802_11_key_material,
  301. cmd_act_set,
  302. cmd_option_waitforrsp,
  303. 0, assoc_req);
  304. out:
  305. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  306. return ret;
  307. }
  308. static int assoc_helper_wpa_ie(wlan_private *priv,
  309. struct assoc_request * assoc_req)
  310. {
  311. wlan_adapter *adapter = priv->adapter;
  312. int ret = 0;
  313. lbs_deb_enter(LBS_DEB_ASSOC);
  314. if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
  315. memcpy(&adapter->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
  316. adapter->wpa_ie_len = assoc_req->wpa_ie_len;
  317. } else {
  318. memset(&adapter->wpa_ie, 0, MAX_WPA_IE_LEN);
  319. adapter->wpa_ie_len = 0;
  320. }
  321. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  322. return ret;
  323. }
  324. static int should_deauth_infrastructure(wlan_adapter *adapter,
  325. struct assoc_request * assoc_req)
  326. {
  327. if (adapter->connect_status != libertas_connected)
  328. return 0;
  329. if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
  330. lbs_deb_assoc("Deauthenticating due to new SSID in "
  331. " configuration request.\n");
  332. return 1;
  333. }
  334. if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
  335. if (adapter->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
  336. lbs_deb_assoc("Deauthenticating due to updated security "
  337. "info in configuration request.\n");
  338. return 1;
  339. }
  340. }
  341. if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
  342. lbs_deb_assoc("Deauthenticating due to new BSSID in "
  343. " configuration request.\n");
  344. return 1;
  345. }
  346. /* FIXME: deal with 'auto' mode somehow */
  347. if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
  348. if (assoc_req->mode != IW_MODE_INFRA)
  349. return 1;
  350. }
  351. return 0;
  352. }
  353. static int should_stop_adhoc(wlan_adapter *adapter,
  354. struct assoc_request * assoc_req)
  355. {
  356. if (adapter->connect_status != libertas_connected)
  357. return 0;
  358. if (adapter->curbssparams.ssid.ssidlength != assoc_req->ssid.ssidlength)
  359. return 1;
  360. if (memcmp(adapter->curbssparams.ssid.ssid, assoc_req->ssid.ssid,
  361. adapter->curbssparams.ssid.ssidlength))
  362. return 1;
  363. /* FIXME: deal with 'auto' mode somehow */
  364. if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
  365. if (assoc_req->mode != IW_MODE_ADHOC)
  366. return 1;
  367. }
  368. if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
  369. if (assoc_req->channel != adapter->curbssparams.channel)
  370. return 1;
  371. }
  372. return 0;
  373. }
  374. void libertas_association_worker(struct work_struct *work)
  375. {
  376. wlan_private *priv = container_of(work, wlan_private, assoc_work.work);
  377. wlan_adapter *adapter = priv->adapter;
  378. struct assoc_request * assoc_req = NULL;
  379. int ret = 0;
  380. int find_any_ssid = 0;
  381. lbs_deb_enter(LBS_DEB_ASSOC);
  382. mutex_lock(&adapter->lock);
  383. assoc_req = adapter->pending_assoc_req;
  384. adapter->pending_assoc_req = NULL;
  385. adapter->in_progress_assoc_req = assoc_req;
  386. mutex_unlock(&adapter->lock);
  387. if (!assoc_req)
  388. goto done;
  389. print_assoc_req(__func__, assoc_req);
  390. /* If 'any' SSID was specified, find an SSID to associate with */
  391. if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
  392. && !assoc_req->ssid.ssidlength)
  393. find_any_ssid = 1;
  394. /* But don't use 'any' SSID if there's a valid locked BSSID to use */
  395. if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
  396. if (memcmp(&assoc_req->bssid, bssid_any, ETH_ALEN)
  397. && memcmp(&assoc_req->bssid, bssid_off, ETH_ALEN))
  398. find_any_ssid = 0;
  399. }
  400. if (find_any_ssid) {
  401. u8 new_mode;
  402. ret = libertas_find_best_network_SSID(priv, &assoc_req->ssid,
  403. assoc_req->mode, &new_mode);
  404. if (ret) {
  405. lbs_deb_assoc("Could not find best network\n");
  406. ret = -ENETUNREACH;
  407. goto out;
  408. }
  409. /* Ensure we switch to the mode of the AP */
  410. if (assoc_req->mode == IW_MODE_AUTO) {
  411. set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
  412. assoc_req->mode = new_mode;
  413. }
  414. }
  415. /*
  416. * Check if the attributes being changing require deauthentication
  417. * from the currently associated infrastructure access point.
  418. */
  419. if (adapter->mode == IW_MODE_INFRA) {
  420. if (should_deauth_infrastructure(adapter, assoc_req)) {
  421. ret = libertas_send_deauthentication(priv);
  422. if (ret) {
  423. lbs_deb_assoc("Deauthentication due to new "
  424. "configuration request failed: %d\n",
  425. ret);
  426. }
  427. }
  428. } else if (adapter->mode == IW_MODE_ADHOC) {
  429. if (should_stop_adhoc(adapter, assoc_req)) {
  430. ret = libertas_stop_adhoc_network(priv);
  431. if (ret) {
  432. lbs_deb_assoc("Teardown of AdHoc network due to "
  433. "new configuration request failed: %d\n",
  434. ret);
  435. }
  436. }
  437. }
  438. /* Send the various configuration bits to the firmware */
  439. if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
  440. ret = assoc_helper_mode(priv, assoc_req);
  441. if (ret) {
  442. lbs_deb_assoc("ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
  443. goto out;
  444. }
  445. }
  446. if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
  447. ret = assoc_helper_channel(priv, assoc_req);
  448. if (ret) {
  449. lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n",
  450. __LINE__, ret);
  451. goto out;
  452. }
  453. }
  454. if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
  455. || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
  456. ret = assoc_helper_wep_keys(priv, assoc_req);
  457. if (ret) {
  458. lbs_deb_assoc("ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret);
  459. goto out;
  460. }
  461. }
  462. if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
  463. ret = assoc_helper_secinfo(priv, assoc_req);
  464. if (ret) {
  465. lbs_deb_assoc("ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret);
  466. goto out;
  467. }
  468. }
  469. if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
  470. ret = assoc_helper_wpa_ie(priv, assoc_req);
  471. if (ret) {
  472. lbs_deb_assoc("ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret);
  473. goto out;
  474. }
  475. }
  476. if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
  477. || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
  478. ret = assoc_helper_wpa_keys(priv, assoc_req);
  479. if (ret) {
  480. lbs_deb_assoc("ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
  481. goto out;
  482. }
  483. }
  484. /* SSID/BSSID should be the _last_ config option set, because they
  485. * trigger the association attempt.
  486. */
  487. if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)
  488. || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
  489. int success = 1;
  490. ret = assoc_helper_associate(priv, assoc_req);
  491. if (ret) {
  492. lbs_deb_assoc("ASSOC: association attempt unsuccessful: %d\n",
  493. ret);
  494. success = 0;
  495. }
  496. if (adapter->connect_status != libertas_connected) {
  497. lbs_deb_assoc("ASSOC: assoication attempt unsuccessful, "
  498. "not connected.\n");
  499. success = 0;
  500. }
  501. if (success) {
  502. lbs_deb_assoc("ASSOC: association attempt successful. "
  503. "Associated to '%s' (" MAC_FMT ")\n",
  504. libertas_escape_essid(adapter->curbssparams.ssid.ssid,
  505. adapter->curbssparams.ssid.ssidlength),
  506. MAC_ARG(adapter->curbssparams.bssid));
  507. libertas_prepare_and_send_command(priv,
  508. cmd_802_11_rssi,
  509. 0, cmd_option_waitforrsp, 0, NULL);
  510. libertas_prepare_and_send_command(priv,
  511. cmd_802_11_get_log,
  512. 0, cmd_option_waitforrsp, 0, NULL);
  513. } else {
  514. ret = -1;
  515. }
  516. }
  517. out:
  518. if (ret) {
  519. lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
  520. ret);
  521. }
  522. mutex_lock(&adapter->lock);
  523. adapter->in_progress_assoc_req = NULL;
  524. mutex_unlock(&adapter->lock);
  525. kfree(assoc_req);
  526. done:
  527. lbs_deb_leave(LBS_DEB_ASSOC);
  528. }
  529. /*
  530. * Caller MUST hold any necessary locks
  531. */
  532. struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
  533. {
  534. struct assoc_request * assoc_req;
  535. if (!adapter->pending_assoc_req) {
  536. adapter->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
  537. GFP_KERNEL);
  538. if (!adapter->pending_assoc_req) {
  539. lbs_pr_info("Not enough memory to allocate association"
  540. " request!\n");
  541. return NULL;
  542. }
  543. }
  544. /* Copy current configuration attributes to the association request,
  545. * but don't overwrite any that are already set.
  546. */
  547. assoc_req = adapter->pending_assoc_req;
  548. if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
  549. memcpy(&assoc_req->ssid, &adapter->curbssparams.ssid,
  550. sizeof(struct WLAN_802_11_SSID));
  551. }
  552. if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
  553. assoc_req->channel = adapter->curbssparams.channel;
  554. if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
  555. assoc_req->band = adapter->curbssparams.band;
  556. if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
  557. assoc_req->mode = adapter->mode;
  558. if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
  559. memcpy(&assoc_req->bssid, adapter->curbssparams.bssid,
  560. ETH_ALEN);
  561. }
  562. if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
  563. int i;
  564. for (i = 0; i < 4; i++) {
  565. memcpy(&assoc_req->wep_keys[i], &adapter->wep_keys[i],
  566. sizeof(struct WLAN_802_11_KEY));
  567. }
  568. }
  569. if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
  570. assoc_req->wep_tx_keyidx = adapter->wep_tx_keyidx;
  571. if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
  572. memcpy(&assoc_req->wpa_mcast_key, &adapter->wpa_mcast_key,
  573. sizeof(struct WLAN_802_11_KEY));
  574. }
  575. if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
  576. memcpy(&assoc_req->wpa_unicast_key, &adapter->wpa_unicast_key,
  577. sizeof(struct WLAN_802_11_KEY));
  578. }
  579. if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
  580. memcpy(&assoc_req->secinfo, &adapter->secinfo,
  581. sizeof(struct wlan_802_11_security));
  582. }
  583. if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
  584. memcpy(&assoc_req->wpa_ie, &adapter->wpa_ie,
  585. MAX_WPA_IE_LEN);
  586. assoc_req->wpa_ie_len = adapter->wpa_ie_len;
  587. }
  588. print_assoc_req(__func__, assoc_req);
  589. return assoc_req;
  590. }