assoc.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849
  1. /* Copyright (C) 2006, Red Hat, Inc. */
  2. #include <linux/types.h>
  3. #include <linux/etherdevice.h>
  4. #include <linux/ieee80211.h>
  5. #include <linux/if_arp.h>
  6. #include <net/lib80211.h>
  7. #include "assoc.h"
  8. #include "decl.h"
  9. #include "host.h"
  10. #include "scan.h"
  11. #include "cmd.h"
  12. static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
  13. { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  14. static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
  15. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  16. /* The firmware needs the following bits masked out of the beacon-derived
  17. * capability field when associating/joining to a BSS:
  18. * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused)
  19. */
  20. #define CAPINFO_MASK (~(0xda00))
  21. /**
  22. * @brief This function finds common rates between rates and card rates.
  23. *
  24. * It will fill common rates in rates as output if found.
  25. *
  26. * NOTE: Setting the MSB of the basic rates need to be taken
  27. * care, either before or after calling this function
  28. *
  29. * @param priv A pointer to struct lbs_private structure
  30. * @param rates the buffer which keeps input and output
  31. * @param rates_size the size of rates buffer; new size of buffer on return,
  32. * which will be less than or equal to original rates_size
  33. *
  34. * @return 0 on success, or -1 on error
  35. */
  36. static int get_common_rates(struct lbs_private *priv,
  37. u8 *rates,
  38. u16 *rates_size)
  39. {
  40. int i, j;
  41. u8 intersection[MAX_RATES];
  42. u16 intersection_size;
  43. u16 num_rates = 0;
  44. intersection_size = min_t(u16, *rates_size, ARRAY_SIZE(intersection));
  45. /* Allow each rate from 'rates' that is supported by the hardware */
  46. for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && lbs_bg_rates[i]; i++) {
  47. for (j = 0; j < intersection_size && rates[j]; j++) {
  48. if (rates[j] == lbs_bg_rates[i])
  49. intersection[num_rates++] = rates[j];
  50. }
  51. }
  52. lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
  53. lbs_deb_hex(LBS_DEB_JOIN, "card rates ", lbs_bg_rates,
  54. ARRAY_SIZE(lbs_bg_rates));
  55. lbs_deb_hex(LBS_DEB_JOIN, "common rates", intersection, num_rates);
  56. lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
  57. if (!priv->enablehwauto) {
  58. for (i = 0; i < num_rates; i++) {
  59. if (intersection[i] == priv->cur_rate)
  60. goto done;
  61. }
  62. lbs_pr_alert("Previously set fixed data rate %#x isn't "
  63. "compatible with the network.\n", priv->cur_rate);
  64. return -1;
  65. }
  66. done:
  67. memset(rates, 0, *rates_size);
  68. *rates_size = num_rates;
  69. memcpy(rates, intersection, num_rates);
  70. return 0;
  71. }
  72. /**
  73. * @brief Sets the MSB on basic rates as the firmware requires
  74. *
  75. * Scan through an array and set the MSB for basic data rates.
  76. *
  77. * @param rates buffer of data rates
  78. * @param len size of buffer
  79. */
  80. static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
  81. {
  82. int i;
  83. for (i = 0; i < len; i++) {
  84. if (rates[i] == 0x02 || rates[i] == 0x04 ||
  85. rates[i] == 0x0b || rates[i] == 0x16)
  86. rates[i] |= 0x80;
  87. }
  88. }
  89. static u8 iw_auth_to_ieee_auth(u8 auth)
  90. {
  91. if (auth == IW_AUTH_ALG_OPEN_SYSTEM)
  92. return 0x00;
  93. else if (auth == IW_AUTH_ALG_SHARED_KEY)
  94. return 0x01;
  95. else if (auth == IW_AUTH_ALG_LEAP)
  96. return 0x80;
  97. lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth);
  98. return 0;
  99. }
  100. /**
  101. * @brief This function prepares the authenticate command. AUTHENTICATE only
  102. * sets the authentication suite for future associations, as the firmware
  103. * handles authentication internally during the ASSOCIATE command.
  104. *
  105. * @param priv A pointer to struct lbs_private structure
  106. * @param bssid The peer BSSID with which to authenticate
  107. * @param auth The authentication mode to use (from wireless.h)
  108. *
  109. * @return 0 or -1
  110. */
  111. static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth)
  112. {
  113. struct cmd_ds_802_11_authenticate cmd;
  114. int ret = -1;
  115. lbs_deb_enter(LBS_DEB_JOIN);
  116. cmd.hdr.size = cpu_to_le16(sizeof(cmd));
  117. memcpy(cmd.bssid, bssid, ETH_ALEN);
  118. cmd.authtype = iw_auth_to_ieee_auth(auth);
  119. lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype);
  120. ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
  121. lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
  122. return ret;
  123. }
  124. static int lbs_assoc_post(struct lbs_private *priv,
  125. struct cmd_ds_802_11_associate_response *resp)
  126. {
  127. int ret = 0;
  128. union iwreq_data wrqu;
  129. struct bss_descriptor *bss;
  130. u16 status_code;
  131. lbs_deb_enter(LBS_DEB_ASSOC);
  132. if (!priv->in_progress_assoc_req) {
  133. lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
  134. ret = -1;
  135. goto done;
  136. }
  137. bss = &priv->in_progress_assoc_req->bss;
  138. /*
  139. * Older FW versions map the IEEE 802.11 Status Code in the association
  140. * response to the following values returned in resp->statuscode:
  141. *
  142. * IEEE Status Code Marvell Status Code
  143. * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
  144. * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
  145. * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
  146. * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
  147. * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
  148. * others -> 0x0003 ASSOC_RESULT_REFUSED
  149. *
  150. * Other response codes:
  151. * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
  152. * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
  153. * association response from the AP)
  154. */
  155. status_code = le16_to_cpu(resp->statuscode);
  156. if (priv->fwrelease < 0x09000000) {
  157. switch (status_code) {
  158. case 0x00:
  159. break;
  160. case 0x01:
  161. lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
  162. break;
  163. case 0x02:
  164. lbs_deb_assoc("ASSOC_RESP: internal timer "
  165. "expired while waiting for the AP\n");
  166. break;
  167. case 0x03:
  168. lbs_deb_assoc("ASSOC_RESP: association "
  169. "refused by AP\n");
  170. break;
  171. case 0x04:
  172. lbs_deb_assoc("ASSOC_RESP: authentication "
  173. "refused by AP\n");
  174. break;
  175. default:
  176. lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
  177. " unknown\n", status_code);
  178. break;
  179. }
  180. } else {
  181. /* v9+ returns the AP's association response */
  182. lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code);
  183. }
  184. if (status_code) {
  185. lbs_mac_event_disconnected(priv);
  186. ret = -1;
  187. goto done;
  188. }
  189. lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP",
  190. (void *) (resp + sizeof (resp->hdr)),
  191. le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr));
  192. /* Send a Media Connected event, according to the Spec */
  193. priv->connect_status = LBS_CONNECTED;
  194. /* Update current SSID and BSSID */
  195. memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
  196. priv->curbssparams.ssid_len = bss->ssid_len;
  197. memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
  198. priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
  199. priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
  200. memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
  201. memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
  202. priv->nextSNRNF = 0;
  203. priv->numSNRNF = 0;
  204. netif_carrier_on(priv->dev);
  205. if (!priv->tx_pending_len)
  206. netif_wake_queue(priv->dev);
  207. memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
  208. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  209. wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
  210. done:
  211. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  212. return ret;
  213. }
  214. /**
  215. * @brief This function prepares an association-class command.
  216. *
  217. * @param priv A pointer to struct lbs_private structure
  218. * @param assoc_req The association request describing the BSS to associate
  219. * or reassociate with
  220. * @param command The actual command, either CMD_802_11_ASSOCIATE or
  221. * CMD_802_11_REASSOCIATE
  222. *
  223. * @return 0 or -1
  224. */
  225. static int lbs_associate(struct lbs_private *priv,
  226. struct assoc_request *assoc_req,
  227. u16 command)
  228. {
  229. struct cmd_ds_802_11_associate cmd;
  230. int ret = 0;
  231. struct bss_descriptor *bss = &assoc_req->bss;
  232. u8 *pos = &(cmd.iebuf[0]);
  233. u16 tmpcap, tmplen, tmpauth;
  234. struct mrvl_ie_ssid_param_set *ssid;
  235. struct mrvl_ie_ds_param_set *ds;
  236. struct mrvl_ie_cf_param_set *cf;
  237. struct mrvl_ie_rates_param_set *rates;
  238. struct mrvl_ie_rsn_param_set *rsn;
  239. struct mrvl_ie_auth_type *auth;
  240. lbs_deb_enter(LBS_DEB_ASSOC);
  241. BUG_ON((command != CMD_802_11_ASSOCIATE) &&
  242. (command != CMD_802_11_REASSOCIATE));
  243. memset(&cmd, 0, sizeof(cmd));
  244. cmd.hdr.command = cpu_to_le16(command);
  245. /* Fill in static fields */
  246. memcpy(cmd.bssid, bss->bssid, ETH_ALEN);
  247. cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
  248. /* Capability info */
  249. tmpcap = (bss->capability & CAPINFO_MASK);
  250. if (bss->mode == IW_MODE_INFRA)
  251. tmpcap |= WLAN_CAPABILITY_ESS;
  252. cmd.capability = cpu_to_le16(tmpcap);
  253. lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
  254. /* SSID */
  255. ssid = (struct mrvl_ie_ssid_param_set *) pos;
  256. ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
  257. tmplen = bss->ssid_len;
  258. ssid->header.len = cpu_to_le16(tmplen);
  259. memcpy(ssid->ssid, bss->ssid, tmplen);
  260. pos += sizeof(ssid->header) + tmplen;
  261. ds = (struct mrvl_ie_ds_param_set *) pos;
  262. ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
  263. ds->header.len = cpu_to_le16(1);
  264. ds->channel = bss->phy.ds.channel;
  265. pos += sizeof(ds->header) + 1;
  266. cf = (struct mrvl_ie_cf_param_set *) pos;
  267. cf->header.type = cpu_to_le16(TLV_TYPE_CF);
  268. tmplen = sizeof(*cf) - sizeof (cf->header);
  269. cf->header.len = cpu_to_le16(tmplen);
  270. /* IE payload should be zeroed, firmware fills it in for us */
  271. pos += sizeof(*cf);
  272. rates = (struct mrvl_ie_rates_param_set *) pos;
  273. rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
  274. tmplen = min_t(u16, ARRAY_SIZE(bss->rates), MAX_RATES);
  275. memcpy(&rates->rates, &bss->rates, tmplen);
  276. if (get_common_rates(priv, rates->rates, &tmplen)) {
  277. ret = -1;
  278. goto done;
  279. }
  280. pos += sizeof(rates->header) + tmplen;
  281. rates->header.len = cpu_to_le16(tmplen);
  282. lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
  283. /* Copy the infra. association rates into Current BSS state structure */
  284. memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
  285. memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
  286. /* Set MSB on basic rates as the firmware requires, but _after_
  287. * copying to current bss rates.
  288. */
  289. lbs_set_basic_rate_flags(rates->rates, tmplen);
  290. /* Firmware v9+ indicate authentication suites as a TLV */
  291. if (priv->fwrelease >= 0x09000000) {
  292. auth = (struct mrvl_ie_auth_type *) pos;
  293. auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
  294. auth->header.len = cpu_to_le16(2);
  295. tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode);
  296. auth->auth = cpu_to_le16(tmpauth);
  297. pos += sizeof(auth->header) + 2;
  298. lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
  299. bss->bssid, priv->secinfo.auth_mode);
  300. }
  301. /* WPA/WPA2 IEs */
  302. if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
  303. rsn = (struct mrvl_ie_rsn_param_set *) pos;
  304. /* WPA_IE or WPA2_IE */
  305. rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
  306. tmplen = (u16) assoc_req->wpa_ie[1];
  307. rsn->header.len = cpu_to_le16(tmplen);
  308. memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
  309. lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn,
  310. sizeof(rsn->header) + tmplen);
  311. pos += sizeof(rsn->header) + tmplen;
  312. }
  313. cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) +
  314. (u16)(pos - (u8 *) &cmd.iebuf));
  315. /* update curbssparams */
  316. priv->curbssparams.channel = bss->phy.ds.channel;
  317. ret = lbs_cmd_with_response(priv, command, &cmd);
  318. if (ret == 0) {
  319. ret = lbs_assoc_post(priv,
  320. (struct cmd_ds_802_11_associate_response *) &cmd);
  321. }
  322. done:
  323. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  324. return ret;
  325. }
  326. /**
  327. * @brief Associate to a specific BSS discovered in a scan
  328. *
  329. * @param priv A pointer to struct lbs_private structure
  330. * @param assoc_req The association request describing the BSS to associate with
  331. *
  332. * @return 0-success, otherwise fail
  333. */
  334. static int lbs_try_associate(struct lbs_private *priv,
  335. struct assoc_request *assoc_req)
  336. {
  337. int ret;
  338. u8 preamble = RADIO_PREAMBLE_LONG;
  339. lbs_deb_enter(LBS_DEB_ASSOC);
  340. /* FW v9 and higher indicate authentication suites as a TLV in the
  341. * association command, not as a separate authentication command.
  342. */
  343. if (priv->fwrelease < 0x09000000) {
  344. ret = lbs_set_authentication(priv, assoc_req->bss.bssid,
  345. priv->secinfo.auth_mode);
  346. if (ret)
  347. goto out;
  348. }
  349. /* Use short preamble only when both the BSS and firmware support it */
  350. if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
  351. (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
  352. preamble = RADIO_PREAMBLE_SHORT;
  353. ret = lbs_set_radio(priv, preamble, 1);
  354. if (ret)
  355. goto out;
  356. ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE);
  357. out:
  358. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  359. return ret;
  360. }
  361. static int lbs_adhoc_post(struct lbs_private *priv,
  362. struct cmd_ds_802_11_ad_hoc_result *resp)
  363. {
  364. int ret = 0;
  365. u16 command = le16_to_cpu(resp->hdr.command);
  366. u16 result = le16_to_cpu(resp->hdr.result);
  367. union iwreq_data wrqu;
  368. struct bss_descriptor *bss;
  369. DECLARE_SSID_BUF(ssid);
  370. lbs_deb_enter(LBS_DEB_JOIN);
  371. if (!priv->in_progress_assoc_req) {
  372. lbs_deb_join("ADHOC_RESP: no in-progress association "
  373. "request\n");
  374. ret = -1;
  375. goto done;
  376. }
  377. bss = &priv->in_progress_assoc_req->bss;
  378. /*
  379. * Join result code 0 --> SUCCESS
  380. */
  381. if (result) {
  382. lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
  383. if (priv->connect_status == LBS_CONNECTED)
  384. lbs_mac_event_disconnected(priv);
  385. ret = -1;
  386. goto done;
  387. }
  388. /* Send a Media Connected event, according to the Spec */
  389. priv->connect_status = LBS_CONNECTED;
  390. if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
  391. /* Update the created network descriptor with the new BSSID */
  392. memcpy(bss->bssid, resp->bssid, ETH_ALEN);
  393. }
  394. /* Set the BSSID from the joined/started descriptor */
  395. memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
  396. /* Set the new SSID to current SSID */
  397. memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
  398. priv->curbssparams.ssid_len = bss->ssid_len;
  399. netif_carrier_on(priv->dev);
  400. if (!priv->tx_pending_len)
  401. netif_wake_queue(priv->dev);
  402. memset(&wrqu, 0, sizeof(wrqu));
  403. memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
  404. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  405. wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
  406. lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
  407. print_ssid(ssid, bss->ssid, bss->ssid_len),
  408. priv->curbssparams.bssid,
  409. priv->curbssparams.channel);
  410. done:
  411. lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
  412. return ret;
  413. }
  414. /**
  415. * @brief Join an adhoc network found in a previous scan
  416. *
  417. * @param priv A pointer to struct lbs_private structure
  418. * @param assoc_req The association request describing the BSS to join
  419. *
  420. * @return 0 on success, error on failure
  421. */
  422. static int lbs_adhoc_join(struct lbs_private *priv,
  423. struct assoc_request *assoc_req)
  424. {
  425. struct cmd_ds_802_11_ad_hoc_join cmd;
  426. struct bss_descriptor *bss = &assoc_req->bss;
  427. u8 preamble = RADIO_PREAMBLE_LONG;
  428. DECLARE_SSID_BUF(ssid);
  429. u16 ratesize = 0;
  430. int ret = 0;
  431. lbs_deb_enter(LBS_DEB_ASSOC);
  432. lbs_deb_join("current SSID '%s', ssid length %u\n",
  433. print_ssid(ssid, priv->curbssparams.ssid,
  434. priv->curbssparams.ssid_len),
  435. priv->curbssparams.ssid_len);
  436. lbs_deb_join("requested ssid '%s', ssid length %u\n",
  437. print_ssid(ssid, bss->ssid, bss->ssid_len),
  438. bss->ssid_len);
  439. /* check if the requested SSID is already joined */
  440. if (priv->curbssparams.ssid_len &&
  441. !lbs_ssid_cmp(priv->curbssparams.ssid,
  442. priv->curbssparams.ssid_len,
  443. bss->ssid, bss->ssid_len) &&
  444. (priv->mode == IW_MODE_ADHOC) &&
  445. (priv->connect_status == LBS_CONNECTED)) {
  446. union iwreq_data wrqu;
  447. lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
  448. "current, not attempting to re-join");
  449. /* Send the re-association event though, because the association
  450. * request really was successful, even if just a null-op.
  451. */
  452. memset(&wrqu, 0, sizeof(wrqu));
  453. memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
  454. ETH_ALEN);
  455. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  456. wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
  457. goto out;
  458. }
  459. /* Use short preamble only when both the BSS and firmware support it */
  460. if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
  461. (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
  462. lbs_deb_join("AdhocJoin: Short preamble\n");
  463. preamble = RADIO_PREAMBLE_SHORT;
  464. }
  465. ret = lbs_set_radio(priv, preamble, 1);
  466. if (ret)
  467. goto out;
  468. lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
  469. lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
  470. priv->adhoccreate = 0;
  471. priv->curbssparams.channel = bss->channel;
  472. /* Build the join command */
  473. memset(&cmd, 0, sizeof(cmd));
  474. cmd.hdr.size = cpu_to_le16(sizeof(cmd));
  475. cmd.bss.type = CMD_BSS_TYPE_IBSS;
  476. cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
  477. memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
  478. memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
  479. memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set));
  480. memcpy(&cmd.bss.ibss, &bss->ss.ibss,
  481. sizeof(struct ieee_ie_ibss_param_set));
  482. cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
  483. lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
  484. bss->capability, CAPINFO_MASK);
  485. /* information on BSSID descriptor passed to FW */
  486. lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n",
  487. cmd.bss.bssid, cmd.bss.ssid);
  488. /* Only v8 and below support setting these */
  489. if (priv->fwrelease < 0x09000000) {
  490. /* failtimeout */
  491. cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
  492. /* probedelay */
  493. cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
  494. }
  495. /* Copy Data rates from the rates recorded in scan response */
  496. memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
  497. ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), ARRAY_SIZE (bss->rates));
  498. memcpy(cmd.bss.rates, bss->rates, ratesize);
  499. if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
  500. lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
  501. ret = -1;
  502. goto out;
  503. }
  504. /* Copy the ad-hoc creation rates into Current BSS state structure */
  505. memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
  506. memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize);
  507. /* Set MSB on basic rates as the firmware requires, but _after_
  508. * copying to current bss rates.
  509. */
  510. lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
  511. cmd.bss.ibss.atimwindow = bss->atimwindow;
  512. if (assoc_req->secinfo.wep_enabled) {
  513. u16 tmp = le16_to_cpu(cmd.bss.capability);
  514. tmp |= WLAN_CAPABILITY_PRIVACY;
  515. cmd.bss.capability = cpu_to_le16(tmp);
  516. }
  517. if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
  518. __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM);
  519. /* wake up first */
  520. ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
  521. CMD_ACT_SET, 0, 0,
  522. &local_ps_mode);
  523. if (ret) {
  524. ret = -1;
  525. goto out;
  526. }
  527. }
  528. ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
  529. if (ret == 0) {
  530. ret = lbs_adhoc_post(priv,
  531. (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
  532. }
  533. out:
  534. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  535. return ret;
  536. }
  537. /**
  538. * @brief Start an Adhoc Network
  539. *
  540. * @param priv A pointer to struct lbs_private structure
  541. * @param assoc_req The association request describing the BSS to start
  542. *
  543. * @return 0 on success, error on failure
  544. */
  545. static int lbs_adhoc_start(struct lbs_private *priv,
  546. struct assoc_request *assoc_req)
  547. {
  548. struct cmd_ds_802_11_ad_hoc_start cmd;
  549. u8 preamble = RADIO_PREAMBLE_LONG;
  550. size_t ratesize = 0;
  551. u16 tmpcap = 0;
  552. int ret = 0;
  553. DECLARE_SSID_BUF(ssid);
  554. lbs_deb_enter(LBS_DEB_ASSOC);
  555. if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
  556. lbs_deb_join("ADHOC_START: Will use short preamble\n");
  557. preamble = RADIO_PREAMBLE_SHORT;
  558. }
  559. ret = lbs_set_radio(priv, preamble, 1);
  560. if (ret)
  561. goto out;
  562. /* Build the start command */
  563. memset(&cmd, 0, sizeof(cmd));
  564. cmd.hdr.size = cpu_to_le16(sizeof(cmd));
  565. memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
  566. lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
  567. print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
  568. assoc_req->ssid_len);
  569. cmd.bsstype = CMD_BSS_TYPE_IBSS;
  570. if (priv->beacon_period == 0)
  571. priv->beacon_period = MRVDRV_BEACON_INTERVAL;
  572. cmd.beaconperiod = cpu_to_le16(priv->beacon_period);
  573. WARN_ON(!assoc_req->channel);
  574. /* set Physical parameter set */
  575. cmd.ds.header.id = WLAN_EID_DS_PARAMS;
  576. cmd.ds.header.len = 1;
  577. cmd.ds.channel = assoc_req->channel;
  578. /* set IBSS parameter set */
  579. cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS;
  580. cmd.ibss.header.len = 2;
  581. cmd.ibss.atimwindow = cpu_to_le16(0);
  582. /* set capability info */
  583. tmpcap = WLAN_CAPABILITY_IBSS;
  584. if (assoc_req->secinfo.wep_enabled ||
  585. assoc_req->secinfo.WPAenabled ||
  586. assoc_req->secinfo.WPA2enabled) {
  587. lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n");
  588. tmpcap |= WLAN_CAPABILITY_PRIVACY;
  589. } else
  590. lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n");
  591. cmd.capability = cpu_to_le16(tmpcap);
  592. /* Only v8 and below support setting probe delay */
  593. if (priv->fwrelease < 0x09000000)
  594. cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
  595. ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates));
  596. memcpy(cmd.rates, lbs_bg_rates, ratesize);
  597. /* Copy the ad-hoc creating rates into Current BSS state structure */
  598. memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
  599. memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize);
  600. /* Set MSB on basic rates as the firmware requires, but _after_
  601. * copying to current bss rates.
  602. */
  603. lbs_set_basic_rate_flags(cmd.rates, ratesize);
  604. lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
  605. cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
  606. lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
  607. assoc_req->channel, assoc_req->band);
  608. priv->adhoccreate = 1;
  609. priv->mode = IW_MODE_ADHOC;
  610. ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
  611. if (ret == 0)
  612. ret = lbs_adhoc_post(priv,
  613. (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
  614. out:
  615. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  616. return ret;
  617. }
  618. /**
  619. * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode
  620. *
  621. * @param priv A pointer to struct lbs_private structure
  622. * @return 0 on success, or an error
  623. */
  624. int lbs_adhoc_stop(struct lbs_private *priv)
  625. {
  626. struct cmd_ds_802_11_ad_hoc_stop cmd;
  627. int ret;
  628. lbs_deb_enter(LBS_DEB_JOIN);
  629. memset(&cmd, 0, sizeof (cmd));
  630. cmd.hdr.size = cpu_to_le16 (sizeof (cmd));
  631. ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
  632. /* Clean up everything even if there was an error */
  633. lbs_mac_event_disconnected(priv);
  634. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  635. return ret;
  636. }
  637. static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
  638. struct bss_descriptor *match_bss)
  639. {
  640. if (!secinfo->wep_enabled && !secinfo->WPAenabled
  641. && !secinfo->WPA2enabled
  642. && match_bss->wpa_ie[0] != WLAN_EID_GENERIC
  643. && match_bss->rsn_ie[0] != WLAN_EID_RSN
  644. && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
  645. return 1;
  646. else
  647. return 0;
  648. }
  649. static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
  650. struct bss_descriptor *match_bss)
  651. {
  652. if (secinfo->wep_enabled && !secinfo->WPAenabled
  653. && !secinfo->WPA2enabled
  654. && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
  655. return 1;
  656. else
  657. return 0;
  658. }
  659. static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
  660. struct bss_descriptor *match_bss)
  661. {
  662. if (!secinfo->wep_enabled && secinfo->WPAenabled
  663. && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
  664. /* privacy bit may NOT be set in some APs like LinkSys WRT54G
  665. && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
  666. )
  667. return 1;
  668. else
  669. return 0;
  670. }
  671. static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
  672. struct bss_descriptor *match_bss)
  673. {
  674. if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
  675. (match_bss->rsn_ie[0] == WLAN_EID_RSN)
  676. /* privacy bit may NOT be set in some APs like LinkSys WRT54G
  677. (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
  678. )
  679. return 1;
  680. else
  681. return 0;
  682. }
  683. static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
  684. struct bss_descriptor *match_bss)
  685. {
  686. if (!secinfo->wep_enabled && !secinfo->WPAenabled
  687. && !secinfo->WPA2enabled
  688. && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC)
  689. && (match_bss->rsn_ie[0] != WLAN_EID_RSN)
  690. && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
  691. return 1;
  692. else
  693. return 0;
  694. }
  695. /**
  696. * @brief Check if a scanned network compatible with the driver settings
  697. *
  698. * WEP WPA WPA2 ad-hoc encrypt Network
  699. * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
  700. * 0 0 0 0 NONE 0 0 0 yes No security
  701. * 1 0 0 0 NONE 1 0 0 yes Static WEP
  702. * 0 1 0 0 x 1x 1 x yes WPA
  703. * 0 0 1 0 x 1x x 1 yes WPA2
  704. * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
  705. * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
  706. *
  707. *
  708. * @param priv A pointer to struct lbs_private
  709. * @param index Index in scantable to check against current driver settings
  710. * @param mode Network mode: Infrastructure or IBSS
  711. *
  712. * @return Index in scantable, or error code if negative
  713. */
  714. static int is_network_compatible(struct lbs_private *priv,
  715. struct bss_descriptor *bss, uint8_t mode)
  716. {
  717. int matched = 0;
  718. lbs_deb_enter(LBS_DEB_SCAN);
  719. if (bss->mode != mode)
  720. goto done;
  721. matched = match_bss_no_security(&priv->secinfo, bss);
  722. if (matched)
  723. goto done;
  724. matched = match_bss_static_wep(&priv->secinfo, bss);
  725. if (matched)
  726. goto done;
  727. matched = match_bss_wpa(&priv->secinfo, bss);
  728. if (matched) {
  729. lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
  730. "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
  731. "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
  732. priv->secinfo.wep_enabled ? "e" : "d",
  733. priv->secinfo.WPAenabled ? "e" : "d",
  734. priv->secinfo.WPA2enabled ? "e" : "d",
  735. (bss->capability & WLAN_CAPABILITY_PRIVACY));
  736. goto done;
  737. }
  738. matched = match_bss_wpa2(&priv->secinfo, bss);
  739. if (matched) {
  740. lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
  741. "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
  742. "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
  743. priv->secinfo.wep_enabled ? "e" : "d",
  744. priv->secinfo.WPAenabled ? "e" : "d",
  745. priv->secinfo.WPA2enabled ? "e" : "d",
  746. (bss->capability & WLAN_CAPABILITY_PRIVACY));
  747. goto done;
  748. }
  749. matched = match_bss_dynamic_wep(&priv->secinfo, bss);
  750. if (matched) {
  751. lbs_deb_scan("is_network_compatible() dynamic WEP: "
  752. "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
  753. bss->wpa_ie[0], bss->rsn_ie[0],
  754. (bss->capability & WLAN_CAPABILITY_PRIVACY));
  755. goto done;
  756. }
  757. /* bss security settings don't match those configured on card */
  758. lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
  759. "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
  760. bss->wpa_ie[0], bss->rsn_ie[0],
  761. priv->secinfo.wep_enabled ? "e" : "d",
  762. priv->secinfo.WPAenabled ? "e" : "d",
  763. priv->secinfo.WPA2enabled ? "e" : "d",
  764. (bss->capability & WLAN_CAPABILITY_PRIVACY));
  765. done:
  766. lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
  767. return matched;
  768. }
  769. /**
  770. * @brief This function finds a specific compatible BSSID in the scan list
  771. *
  772. * Used in association code
  773. *
  774. * @param priv A pointer to struct lbs_private
  775. * @param bssid BSSID to find in the scan list
  776. * @param mode Network mode: Infrastructure or IBSS
  777. *
  778. * @return index in BSSID list, or error return code (< 0)
  779. */
  780. static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
  781. uint8_t *bssid, uint8_t mode)
  782. {
  783. struct bss_descriptor *iter_bss;
  784. struct bss_descriptor *found_bss = NULL;
  785. lbs_deb_enter(LBS_DEB_SCAN);
  786. if (!bssid)
  787. goto out;
  788. lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
  789. /* Look through the scan table for a compatible match. The loop will
  790. * continue past a matched bssid that is not compatible in case there
  791. * is an AP with multiple SSIDs assigned to the same BSSID
  792. */
  793. mutex_lock(&priv->lock);
  794. list_for_each_entry(iter_bss, &priv->network_list, list) {
  795. if (compare_ether_addr(iter_bss->bssid, bssid))
  796. continue; /* bssid doesn't match */
  797. switch (mode) {
  798. case IW_MODE_INFRA:
  799. case IW_MODE_ADHOC:
  800. if (!is_network_compatible(priv, iter_bss, mode))
  801. break;
  802. found_bss = iter_bss;
  803. break;
  804. default:
  805. found_bss = iter_bss;
  806. break;
  807. }
  808. }
  809. mutex_unlock(&priv->lock);
  810. out:
  811. lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
  812. return found_bss;
  813. }
  814. /**
  815. * @brief This function finds ssid in ssid list.
  816. *
  817. * Used in association code
  818. *
  819. * @param priv A pointer to struct lbs_private
  820. * @param ssid SSID to find in the list
  821. * @param bssid BSSID to qualify the SSID selection (if provided)
  822. * @param mode Network mode: Infrastructure or IBSS
  823. *
  824. * @return index in BSSID list
  825. */
  826. static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
  827. uint8_t *ssid, uint8_t ssid_len,
  828. uint8_t *bssid, uint8_t mode,
  829. int channel)
  830. {
  831. u32 bestrssi = 0;
  832. struct bss_descriptor *iter_bss = NULL;
  833. struct bss_descriptor *found_bss = NULL;
  834. struct bss_descriptor *tmp_oldest = NULL;
  835. lbs_deb_enter(LBS_DEB_SCAN);
  836. mutex_lock(&priv->lock);
  837. list_for_each_entry(iter_bss, &priv->network_list, list) {
  838. if (!tmp_oldest ||
  839. (iter_bss->last_scanned < tmp_oldest->last_scanned))
  840. tmp_oldest = iter_bss;
  841. if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
  842. ssid, ssid_len) != 0)
  843. continue; /* ssid doesn't match */
  844. if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
  845. continue; /* bssid doesn't match */
  846. if ((channel > 0) && (iter_bss->channel != channel))
  847. continue; /* channel doesn't match */
  848. switch (mode) {
  849. case IW_MODE_INFRA:
  850. case IW_MODE_ADHOC:
  851. if (!is_network_compatible(priv, iter_bss, mode))
  852. break;
  853. if (bssid) {
  854. /* Found requested BSSID */
  855. found_bss = iter_bss;
  856. goto out;
  857. }
  858. if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
  859. bestrssi = SCAN_RSSI(iter_bss->rssi);
  860. found_bss = iter_bss;
  861. }
  862. break;
  863. case IW_MODE_AUTO:
  864. default:
  865. if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
  866. bestrssi = SCAN_RSSI(iter_bss->rssi);
  867. found_bss = iter_bss;
  868. }
  869. break;
  870. }
  871. }
  872. out:
  873. mutex_unlock(&priv->lock);
  874. lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
  875. return found_bss;
  876. }
  877. static int assoc_helper_essid(struct lbs_private *priv,
  878. struct assoc_request * assoc_req)
  879. {
  880. int ret = 0;
  881. struct bss_descriptor * bss;
  882. int channel = -1;
  883. DECLARE_SSID_BUF(ssid);
  884. lbs_deb_enter(LBS_DEB_ASSOC);
  885. /* FIXME: take channel into account when picking SSIDs if a channel
  886. * is set.
  887. */
  888. if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
  889. channel = assoc_req->channel;
  890. lbs_deb_assoc("SSID '%s' requested\n",
  891. print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len));
  892. if (assoc_req->mode == IW_MODE_INFRA) {
  893. lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
  894. assoc_req->ssid_len);
  895. bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
  896. assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
  897. if (bss != NULL) {
  898. memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
  899. ret = lbs_try_associate(priv, assoc_req);
  900. } else {
  901. lbs_deb_assoc("SSID not found; cannot associate\n");
  902. }
  903. } else if (assoc_req->mode == IW_MODE_ADHOC) {
  904. /* Scan for the network, do not save previous results. Stale
  905. * scan data will cause us to join a non-existant adhoc network
  906. */
  907. lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
  908. assoc_req->ssid_len);
  909. /* Search for the requested SSID in the scan table */
  910. bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
  911. assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
  912. if (bss != NULL) {
  913. lbs_deb_assoc("SSID found, will join\n");
  914. memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
  915. lbs_adhoc_join(priv, assoc_req);
  916. } else {
  917. /* else send START command */
  918. lbs_deb_assoc("SSID not found, creating adhoc network\n");
  919. memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
  920. IEEE80211_MAX_SSID_LEN);
  921. assoc_req->bss.ssid_len = assoc_req->ssid_len;
  922. lbs_adhoc_start(priv, assoc_req);
  923. }
  924. }
  925. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  926. return ret;
  927. }
  928. static int assoc_helper_bssid(struct lbs_private *priv,
  929. struct assoc_request * assoc_req)
  930. {
  931. int ret = 0;
  932. struct bss_descriptor * bss;
  933. lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid);
  934. /* Search for index position in list for requested MAC */
  935. bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
  936. assoc_req->mode);
  937. if (bss == NULL) {
  938. lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, "
  939. "cannot associate.\n", assoc_req->bssid);
  940. goto out;
  941. }
  942. memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
  943. if (assoc_req->mode == IW_MODE_INFRA) {
  944. ret = lbs_try_associate(priv, assoc_req);
  945. lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n",
  946. ret);
  947. } else if (assoc_req->mode == IW_MODE_ADHOC) {
  948. lbs_adhoc_join(priv, assoc_req);
  949. }
  950. out:
  951. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  952. return ret;
  953. }
  954. static int assoc_helper_associate(struct lbs_private *priv,
  955. struct assoc_request * assoc_req)
  956. {
  957. int ret = 0, done = 0;
  958. lbs_deb_enter(LBS_DEB_ASSOC);
  959. /* If we're given and 'any' BSSID, try associating based on SSID */
  960. if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
  961. if (compare_ether_addr(bssid_any, assoc_req->bssid)
  962. && compare_ether_addr(bssid_off, assoc_req->bssid)) {
  963. ret = assoc_helper_bssid(priv, assoc_req);
  964. done = 1;
  965. }
  966. }
  967. if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
  968. ret = assoc_helper_essid(priv, assoc_req);
  969. }
  970. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  971. return ret;
  972. }
  973. static int assoc_helper_mode(struct lbs_private *priv,
  974. struct assoc_request * assoc_req)
  975. {
  976. int ret = 0;
  977. lbs_deb_enter(LBS_DEB_ASSOC);
  978. if (assoc_req->mode == priv->mode)
  979. goto done;
  980. if (assoc_req->mode == IW_MODE_INFRA) {
  981. if (priv->psstate != PS_STATE_FULL_POWER)
  982. lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
  983. priv->psmode = LBS802_11POWERMODECAM;
  984. }
  985. priv->mode = assoc_req->mode;
  986. ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode);
  987. done:
  988. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  989. return ret;
  990. }
  991. static int assoc_helper_channel(struct lbs_private *priv,
  992. struct assoc_request * assoc_req)
  993. {
  994. int ret = 0;
  995. lbs_deb_enter(LBS_DEB_ASSOC);
  996. ret = lbs_update_channel(priv);
  997. if (ret) {
  998. lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
  999. goto done;
  1000. }
  1001. if (assoc_req->channel == priv->curbssparams.channel)
  1002. goto done;
  1003. if (priv->mesh_dev) {
  1004. /* Change mesh channel first; 21.p21 firmware won't let
  1005. you change channel otherwise (even though it'll return
  1006. an error to this */
  1007. lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
  1008. assoc_req->channel);
  1009. }
  1010. lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
  1011. priv->curbssparams.channel, assoc_req->channel);
  1012. ret = lbs_set_channel(priv, assoc_req->channel);
  1013. if (ret < 0)
  1014. lbs_deb_assoc("ASSOC: channel: error setting channel.\n");
  1015. /* FIXME: shouldn't need to grab the channel _again_ after setting
  1016. * it since the firmware is supposed to return the new channel, but
  1017. * whatever... */
  1018. ret = lbs_update_channel(priv);
  1019. if (ret) {
  1020. lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
  1021. goto done;
  1022. }
  1023. if (assoc_req->channel != priv->curbssparams.channel) {
  1024. lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
  1025. assoc_req->channel);
  1026. goto restore_mesh;
  1027. }
  1028. if ( assoc_req->secinfo.wep_enabled
  1029. && (assoc_req->wep_keys[0].len
  1030. || assoc_req->wep_keys[1].len
  1031. || assoc_req->wep_keys[2].len
  1032. || assoc_req->wep_keys[3].len)) {
  1033. /* Make sure WEP keys are re-sent to firmware */
  1034. set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
  1035. }
  1036. /* Must restart/rejoin adhoc networks after channel change */
  1037. set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
  1038. restore_mesh:
  1039. if (priv->mesh_dev)
  1040. lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
  1041. priv->curbssparams.channel);
  1042. done:
  1043. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  1044. return ret;
  1045. }
  1046. static int assoc_helper_wep_keys(struct lbs_private *priv,
  1047. struct assoc_request *assoc_req)
  1048. {
  1049. int i;
  1050. int ret = 0;
  1051. lbs_deb_enter(LBS_DEB_ASSOC);
  1052. /* Set or remove WEP keys */
  1053. if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
  1054. assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)
  1055. ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req);
  1056. else
  1057. ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req);
  1058. if (ret)
  1059. goto out;
  1060. /* enable/disable the MAC's WEP packet filter */
  1061. if (assoc_req->secinfo.wep_enabled)
  1062. priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
  1063. else
  1064. priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
  1065. lbs_set_mac_control(priv);
  1066. mutex_lock(&priv->lock);
  1067. /* Copy WEP keys into priv wep key fields */
  1068. for (i = 0; i < 4; i++) {
  1069. memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i],
  1070. sizeof(struct enc_key));
  1071. }
  1072. priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
  1073. mutex_unlock(&priv->lock);
  1074. out:
  1075. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  1076. return ret;
  1077. }
  1078. static int assoc_helper_secinfo(struct lbs_private *priv,
  1079. struct assoc_request * assoc_req)
  1080. {
  1081. int ret = 0;
  1082. uint16_t do_wpa;
  1083. uint16_t rsn = 0;
  1084. lbs_deb_enter(LBS_DEB_ASSOC);
  1085. memcpy(&priv->secinfo, &assoc_req->secinfo,
  1086. sizeof(struct lbs_802_11_security));
  1087. lbs_set_mac_control(priv);
  1088. /* If RSN is already enabled, don't try to enable it again, since
  1089. * ENABLE_RSN resets internal state machines and will clobber the
  1090. * 4-way WPA handshake.
  1091. */
  1092. /* Get RSN enabled/disabled */
  1093. ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn);
  1094. if (ret) {
  1095. lbs_deb_assoc("Failed to get RSN status: %d\n", ret);
  1096. goto out;
  1097. }
  1098. /* Don't re-enable RSN if it's already enabled */
  1099. do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled;
  1100. if (do_wpa == rsn)
  1101. goto out;
  1102. /* Set RSN enabled/disabled */
  1103. ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa);
  1104. out:
  1105. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  1106. return ret;
  1107. }
  1108. static int assoc_helper_wpa_keys(struct lbs_private *priv,
  1109. struct assoc_request * assoc_req)
  1110. {
  1111. int ret = 0;
  1112. unsigned int flags = assoc_req->flags;
  1113. lbs_deb_enter(LBS_DEB_ASSOC);
  1114. /* Work around older firmware bug where WPA unicast and multicast
  1115. * keys must be set independently. Seen in SDIO parts with firmware
  1116. * version 5.0.11p0.
  1117. */
  1118. if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
  1119. clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
  1120. ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
  1121. assoc_req->flags = flags;
  1122. }
  1123. if (ret)
  1124. goto out;
  1125. memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key,
  1126. sizeof(struct enc_key));
  1127. if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
  1128. clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
  1129. ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
  1130. assoc_req->flags = flags;
  1131. memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key,
  1132. sizeof(struct enc_key));
  1133. }
  1134. out:
  1135. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  1136. return ret;
  1137. }
  1138. static int assoc_helper_wpa_ie(struct lbs_private *priv,
  1139. struct assoc_request * assoc_req)
  1140. {
  1141. int ret = 0;
  1142. lbs_deb_enter(LBS_DEB_ASSOC);
  1143. if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
  1144. memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
  1145. priv->wpa_ie_len = assoc_req->wpa_ie_len;
  1146. } else {
  1147. memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN);
  1148. priv->wpa_ie_len = 0;
  1149. }
  1150. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  1151. return ret;
  1152. }
  1153. static int should_deauth_infrastructure(struct lbs_private *priv,
  1154. struct assoc_request * assoc_req)
  1155. {
  1156. int ret = 0;
  1157. if (priv->connect_status != LBS_CONNECTED)
  1158. return 0;
  1159. lbs_deb_enter(LBS_DEB_ASSOC);
  1160. if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
  1161. lbs_deb_assoc("Deauthenticating due to new SSID\n");
  1162. ret = 1;
  1163. goto out;
  1164. }
  1165. if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
  1166. if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
  1167. lbs_deb_assoc("Deauthenticating due to new security\n");
  1168. ret = 1;
  1169. goto out;
  1170. }
  1171. }
  1172. if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
  1173. lbs_deb_assoc("Deauthenticating due to new BSSID\n");
  1174. ret = 1;
  1175. goto out;
  1176. }
  1177. if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
  1178. lbs_deb_assoc("Deauthenticating due to channel switch\n");
  1179. ret = 1;
  1180. goto out;
  1181. }
  1182. /* FIXME: deal with 'auto' mode somehow */
  1183. if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
  1184. if (assoc_req->mode != IW_MODE_INFRA) {
  1185. lbs_deb_assoc("Deauthenticating due to leaving "
  1186. "infra mode\n");
  1187. ret = 1;
  1188. goto out;
  1189. }
  1190. }
  1191. out:
  1192. lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
  1193. return ret;
  1194. }
  1195. static int should_stop_adhoc(struct lbs_private *priv,
  1196. struct assoc_request * assoc_req)
  1197. {
  1198. lbs_deb_enter(LBS_DEB_ASSOC);
  1199. if (priv->connect_status != LBS_CONNECTED)
  1200. return 0;
  1201. if (lbs_ssid_cmp(priv->curbssparams.ssid,
  1202. priv->curbssparams.ssid_len,
  1203. assoc_req->ssid, assoc_req->ssid_len) != 0)
  1204. return 1;
  1205. /* FIXME: deal with 'auto' mode somehow */
  1206. if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
  1207. if (assoc_req->mode != IW_MODE_ADHOC)
  1208. return 1;
  1209. }
  1210. if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
  1211. if (assoc_req->channel != priv->curbssparams.channel)
  1212. return 1;
  1213. }
  1214. lbs_deb_leave(LBS_DEB_ASSOC);
  1215. return 0;
  1216. }
  1217. /**
  1218. * @brief This function finds the best SSID in the Scan List
  1219. *
  1220. * Search the scan table for the best SSID that also matches the current
  1221. * adapter network preference (infrastructure or adhoc)
  1222. *
  1223. * @param priv A pointer to struct lbs_private
  1224. *
  1225. * @return index in BSSID list
  1226. */
  1227. static struct bss_descriptor *lbs_find_best_ssid_in_list(
  1228. struct lbs_private *priv, uint8_t mode)
  1229. {
  1230. uint8_t bestrssi = 0;
  1231. struct bss_descriptor *iter_bss;
  1232. struct bss_descriptor *best_bss = NULL;
  1233. lbs_deb_enter(LBS_DEB_SCAN);
  1234. mutex_lock(&priv->lock);
  1235. list_for_each_entry(iter_bss, &priv->network_list, list) {
  1236. switch (mode) {
  1237. case IW_MODE_INFRA:
  1238. case IW_MODE_ADHOC:
  1239. if (!is_network_compatible(priv, iter_bss, mode))
  1240. break;
  1241. if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
  1242. break;
  1243. bestrssi = SCAN_RSSI(iter_bss->rssi);
  1244. best_bss = iter_bss;
  1245. break;
  1246. case IW_MODE_AUTO:
  1247. default:
  1248. if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
  1249. break;
  1250. bestrssi = SCAN_RSSI(iter_bss->rssi);
  1251. best_bss = iter_bss;
  1252. break;
  1253. }
  1254. }
  1255. mutex_unlock(&priv->lock);
  1256. lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
  1257. return best_bss;
  1258. }
  1259. /**
  1260. * @brief Find the best AP
  1261. *
  1262. * Used from association worker.
  1263. *
  1264. * @param priv A pointer to struct lbs_private structure
  1265. * @param pSSID A pointer to AP's ssid
  1266. *
  1267. * @return 0--success, otherwise--fail
  1268. */
  1269. static int lbs_find_best_network_ssid(struct lbs_private *priv,
  1270. uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
  1271. uint8_t *out_mode)
  1272. {
  1273. int ret = -1;
  1274. struct bss_descriptor *found;
  1275. lbs_deb_enter(LBS_DEB_SCAN);
  1276. priv->scan_ssid_len = 0;
  1277. lbs_scan_networks(priv, 1);
  1278. if (priv->surpriseremoved)
  1279. goto out;
  1280. found = lbs_find_best_ssid_in_list(priv, preferred_mode);
  1281. if (found && (found->ssid_len > 0)) {
  1282. memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN);
  1283. *out_ssid_len = found->ssid_len;
  1284. *out_mode = found->mode;
  1285. ret = 0;
  1286. }
  1287. out:
  1288. lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
  1289. return ret;
  1290. }
  1291. void lbs_association_worker(struct work_struct *work)
  1292. {
  1293. struct lbs_private *priv = container_of(work, struct lbs_private,
  1294. assoc_work.work);
  1295. struct assoc_request * assoc_req = NULL;
  1296. int ret = 0;
  1297. int find_any_ssid = 0;
  1298. DECLARE_SSID_BUF(ssid);
  1299. lbs_deb_enter(LBS_DEB_ASSOC);
  1300. mutex_lock(&priv->lock);
  1301. assoc_req = priv->pending_assoc_req;
  1302. priv->pending_assoc_req = NULL;
  1303. priv->in_progress_assoc_req = assoc_req;
  1304. mutex_unlock(&priv->lock);
  1305. if (!assoc_req)
  1306. goto done;
  1307. lbs_deb_assoc(
  1308. "Association Request:\n"
  1309. " flags: 0x%08lx\n"
  1310. " SSID: '%s'\n"
  1311. " chann: %d\n"
  1312. " band: %d\n"
  1313. " mode: %d\n"
  1314. " BSSID: %pM\n"
  1315. " secinfo: %s%s%s\n"
  1316. " auth_mode: %d\n",
  1317. assoc_req->flags,
  1318. print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
  1319. assoc_req->channel, assoc_req->band, assoc_req->mode,
  1320. assoc_req->bssid,
  1321. assoc_req->secinfo.WPAenabled ? " WPA" : "",
  1322. assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
  1323. assoc_req->secinfo.wep_enabled ? " WEP" : "",
  1324. assoc_req->secinfo.auth_mode);
  1325. /* If 'any' SSID was specified, find an SSID to associate with */
  1326. if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
  1327. && !assoc_req->ssid_len)
  1328. find_any_ssid = 1;
  1329. /* But don't use 'any' SSID if there's a valid locked BSSID to use */
  1330. if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
  1331. if (compare_ether_addr(assoc_req->bssid, bssid_any)
  1332. && compare_ether_addr(assoc_req->bssid, bssid_off))
  1333. find_any_ssid = 0;
  1334. }
  1335. if (find_any_ssid) {
  1336. u8 new_mode = assoc_req->mode;
  1337. ret = lbs_find_best_network_ssid(priv, assoc_req->ssid,
  1338. &assoc_req->ssid_len, assoc_req->mode, &new_mode);
  1339. if (ret) {
  1340. lbs_deb_assoc("Could not find best network\n");
  1341. ret = -ENETUNREACH;
  1342. goto out;
  1343. }
  1344. /* Ensure we switch to the mode of the AP */
  1345. if (assoc_req->mode == IW_MODE_AUTO) {
  1346. set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
  1347. assoc_req->mode = new_mode;
  1348. }
  1349. }
  1350. /*
  1351. * Check if the attributes being changing require deauthentication
  1352. * from the currently associated infrastructure access point.
  1353. */
  1354. if (priv->mode == IW_MODE_INFRA) {
  1355. if (should_deauth_infrastructure(priv, assoc_req)) {
  1356. ret = lbs_cmd_80211_deauthenticate(priv,
  1357. priv->curbssparams.bssid,
  1358. WLAN_REASON_DEAUTH_LEAVING);
  1359. if (ret) {
  1360. lbs_deb_assoc("Deauthentication due to new "
  1361. "configuration request failed: %d\n",
  1362. ret);
  1363. }
  1364. }
  1365. } else if (priv->mode == IW_MODE_ADHOC) {
  1366. if (should_stop_adhoc(priv, assoc_req)) {
  1367. ret = lbs_adhoc_stop(priv);
  1368. if (ret) {
  1369. lbs_deb_assoc("Teardown of AdHoc network due to "
  1370. "new configuration request failed: %d\n",
  1371. ret);
  1372. }
  1373. }
  1374. }
  1375. /* Send the various configuration bits to the firmware */
  1376. if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
  1377. ret = assoc_helper_mode(priv, assoc_req);
  1378. if (ret)
  1379. goto out;
  1380. }
  1381. if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
  1382. ret = assoc_helper_channel(priv, assoc_req);
  1383. if (ret)
  1384. goto out;
  1385. }
  1386. if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
  1387. || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
  1388. ret = assoc_helper_wep_keys(priv, assoc_req);
  1389. if (ret)
  1390. goto out;
  1391. }
  1392. if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
  1393. ret = assoc_helper_secinfo(priv, assoc_req);
  1394. if (ret)
  1395. goto out;
  1396. }
  1397. if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
  1398. ret = assoc_helper_wpa_ie(priv, assoc_req);
  1399. if (ret)
  1400. goto out;
  1401. }
  1402. if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
  1403. || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
  1404. ret = assoc_helper_wpa_keys(priv, assoc_req);
  1405. if (ret)
  1406. goto out;
  1407. }
  1408. /* SSID/BSSID should be the _last_ config option set, because they
  1409. * trigger the association attempt.
  1410. */
  1411. if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)
  1412. || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
  1413. int success = 1;
  1414. ret = assoc_helper_associate(priv, assoc_req);
  1415. if (ret) {
  1416. lbs_deb_assoc("ASSOC: association unsuccessful: %d\n",
  1417. ret);
  1418. success = 0;
  1419. }
  1420. if (priv->connect_status != LBS_CONNECTED) {
  1421. lbs_deb_assoc("ASSOC: association unsuccessful, "
  1422. "not connected\n");
  1423. success = 0;
  1424. }
  1425. if (success) {
  1426. lbs_deb_assoc("associated to %pM\n",
  1427. priv->curbssparams.bssid);
  1428. lbs_prepare_and_send_command(priv,
  1429. CMD_802_11_RSSI,
  1430. 0, CMD_OPTION_WAITFORRSP, 0, NULL);
  1431. } else {
  1432. ret = -1;
  1433. }
  1434. }
  1435. out:
  1436. if (ret) {
  1437. lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
  1438. ret);
  1439. }
  1440. mutex_lock(&priv->lock);
  1441. priv->in_progress_assoc_req = NULL;
  1442. mutex_unlock(&priv->lock);
  1443. kfree(assoc_req);
  1444. done:
  1445. lbs_deb_leave(LBS_DEB_ASSOC);
  1446. }
  1447. /*
  1448. * Caller MUST hold any necessary locks
  1449. */
  1450. struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
  1451. {
  1452. struct assoc_request * assoc_req;
  1453. lbs_deb_enter(LBS_DEB_ASSOC);
  1454. if (!priv->pending_assoc_req) {
  1455. priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
  1456. GFP_KERNEL);
  1457. if (!priv->pending_assoc_req) {
  1458. lbs_pr_info("Not enough memory to allocate association"
  1459. " request!\n");
  1460. return NULL;
  1461. }
  1462. }
  1463. /* Copy current configuration attributes to the association request,
  1464. * but don't overwrite any that are already set.
  1465. */
  1466. assoc_req = priv->pending_assoc_req;
  1467. if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
  1468. memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
  1469. IEEE80211_MAX_SSID_LEN);
  1470. assoc_req->ssid_len = priv->curbssparams.ssid_len;
  1471. }
  1472. if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
  1473. assoc_req->channel = priv->curbssparams.channel;
  1474. if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
  1475. assoc_req->band = priv->curbssparams.band;
  1476. if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
  1477. assoc_req->mode = priv->mode;
  1478. if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
  1479. memcpy(&assoc_req->bssid, priv->curbssparams.bssid,
  1480. ETH_ALEN);
  1481. }
  1482. if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
  1483. int i;
  1484. for (i = 0; i < 4; i++) {
  1485. memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i],
  1486. sizeof(struct enc_key));
  1487. }
  1488. }
  1489. if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
  1490. assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx;
  1491. if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
  1492. memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key,
  1493. sizeof(struct enc_key));
  1494. }
  1495. if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
  1496. memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key,
  1497. sizeof(struct enc_key));
  1498. }
  1499. if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
  1500. memcpy(&assoc_req->secinfo, &priv->secinfo,
  1501. sizeof(struct lbs_802_11_security));
  1502. }
  1503. if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
  1504. memcpy(&assoc_req->wpa_ie, &priv->wpa_ie,
  1505. MAX_WPA_IE_LEN);
  1506. assoc_req->wpa_ie_len = priv->wpa_ie_len;
  1507. }
  1508. lbs_deb_leave(LBS_DEB_ASSOC);
  1509. return assoc_req;
  1510. }
  1511. /**
  1512. * @brief Deauthenticate from a specific BSS
  1513. *
  1514. * @param priv A pointer to struct lbs_private structure
  1515. * @param bssid The specific BSS to deauthenticate from
  1516. * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating
  1517. *
  1518. * @return 0 on success, error on failure
  1519. */
  1520. int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN],
  1521. u16 reason)
  1522. {
  1523. struct cmd_ds_802_11_deauthenticate cmd;
  1524. int ret;
  1525. lbs_deb_enter(LBS_DEB_JOIN);
  1526. memset(&cmd, 0, sizeof(cmd));
  1527. cmd.hdr.size = cpu_to_le16(sizeof(cmd));
  1528. memcpy(cmd.macaddr, &bssid[0], ETH_ALEN);
  1529. cmd.reasoncode = cpu_to_le16(reason);
  1530. ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
  1531. /* Clean up everything even if there was an error; can't assume that
  1532. * we're still authenticated to the AP after trying to deauth.
  1533. */
  1534. lbs_mac_event_disconnected(priv);
  1535. lbs_deb_leave(LBS_DEB_JOIN);
  1536. return ret;
  1537. }