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