]>
Commit | Line | Data |
---|---|---|
5449c685 FB |
1 | /* |
2 | * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along | |
16 | * with this program; if not, write to the Free Software Foundation, Inc., | |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | * | |
612822f5 | 19 | * |
5449c685 FB |
20 | * File: wpactl.c |
21 | * | |
22 | * Purpose: handle wpa supplicant ioctl input/out functions | |
23 | * | |
24 | * Author: Lyndon Chen | |
25 | * | |
26 | * Date: Oct. 20, 2003 | |
27 | * | |
28 | * Functions: | |
29 | * | |
30 | * Revision History: | |
31 | * | |
32 | */ | |
33 | ||
5449c685 | 34 | #include "wpactl.h" |
5449c685 | 35 | #include "key.h" |
5449c685 | 36 | #include "mac.h" |
5449c685 | 37 | #include "device.h" |
5449c685 | 38 | #include "wmgr.h" |
5449c685 | 39 | #include "iocmd.h" |
5449c685 | 40 | #include "iowpa.h" |
5449c685 | 41 | #include "rf.h" |
5449c685 FB |
42 | |
43 | /*--------------------- Static Definitions -------------------------*/ | |
44 | ||
45 | #define VIAWGET_WPA_MAX_BUF_SIZE 1024 | |
46 | ||
5449c685 FB |
47 | static const int frequency_list[] = { |
48 | 2412, 2417, 2422, 2427, 2432, 2437, 2442, | |
49 | 2447, 2452, 2457, 2462, 2467, 2472, 2484 | |
50 | }; | |
51 | /*--------------------- Static Classes ----------------------------*/ | |
52 | ||
53 | /*--------------------- Static Variables --------------------------*/ | |
f9cf92bf | 54 | static int msglevel = MSG_LEVEL_INFO; |
5449c685 FB |
55 | |
56 | /*--------------------- Static Functions --------------------------*/ | |
57 | ||
5449c685 | 58 | /*--------------------- Export Variables --------------------------*/ |
5449c685 FB |
59 | static void wpadev_setup(struct net_device *dev) |
60 | { | |
61 | dev->type = ARPHRD_IEEE80211; | |
62 | dev->hard_header_len = ETH_HLEN; | |
63 | dev->mtu = 2048; | |
64 | dev->addr_len = ETH_ALEN; | |
65 | dev->tx_queue_len = 1000; | |
66 | ||
f9cf92bf | 67 | memset(dev->broadcast, 0xFF, ETH_ALEN); |
5449c685 FB |
68 | |
69 | dev->flags = IFF_BROADCAST|IFF_MULTICAST; | |
70 | } | |
71 | ||
5449c685 FB |
72 | /* |
73 | * Description: | |
789d1aef | 74 | * register netdev for wpa supplicant daemon |
5449c685 FB |
75 | * |
76 | * Parameters: | |
77 | * In: | |
78 | * pDevice - | |
79 | * enable - | |
80 | * Out: | |
81 | * | |
82 | * Return Value: | |
83 | * | |
84 | */ | |
85 | ||
86 | static int wpa_init_wpadev(PSDevice pDevice) | |
87 | { | |
f9cf92bf | 88 | PSDevice wpadev_priv; |
5449c685 | 89 | struct net_device *dev = pDevice->dev; |
f9cf92bf | 90 | int ret = 0; |
5449c685 | 91 | |
c835a677 TG |
92 | pDevice->wpadev = alloc_netdev(sizeof(PSDevice), "vntwpa", |
93 | NET_NAME_UNKNOWN, wpadev_setup); | |
5449c685 FB |
94 | if (pDevice->wpadev == NULL) |
95 | return -ENOMEM; | |
96 | ||
f9cf92bf JP |
97 | wpadev_priv = netdev_priv(pDevice->wpadev); |
98 | *wpadev_priv = *pDevice; | |
314cb11b | 99 | eth_hw_addr_inherit(pDevice->wpadev, dev); |
f9cf92bf | 100 | pDevice->wpadev->base_addr = dev->base_addr; |
5449c685 FB |
101 | pDevice->wpadev->irq = dev->irq; |
102 | pDevice->wpadev->mem_start = dev->mem_start; | |
103 | pDevice->wpadev->mem_end = dev->mem_end; | |
104 | ret = register_netdev(pDevice->wpadev); | |
105 | if (ret) { | |
7e809a9b | 106 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n", |
f9cf92bf | 107 | dev->name); |
5449c685 FB |
108 | free_netdev(pDevice->wpadev); |
109 | return -1; | |
110 | } | |
111 | ||
112 | if (pDevice->skb == NULL) { | |
f9cf92bf JP |
113 | pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); |
114 | if (pDevice->skb == NULL) | |
115 | return -ENOMEM; | |
116 | } | |
5449c685 | 117 | |
f9cf92bf JP |
118 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n", |
119 | dev->name, pDevice->wpadev->name); | |
5449c685 FB |
120 | |
121 | return 0; | |
122 | } | |
123 | ||
5449c685 FB |
124 | /* |
125 | * Description: | |
126 | * unregister net_device (wpadev) | |
127 | * | |
128 | * Parameters: | |
129 | * In: | |
130 | * pDevice - | |
131 | * Out: | |
132 | * | |
133 | * Return Value: | |
134 | * | |
135 | */ | |
136 | ||
137 | static int wpa_release_wpadev(PSDevice pDevice) | |
138 | { | |
f9cf92bf JP |
139 | if (pDevice->skb) { |
140 | dev_kfree_skb(pDevice->skb); | |
141 | pDevice->skb = NULL; | |
142 | } | |
143 | ||
144 | if (pDevice->wpadev) { | |
145 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", | |
146 | pDevice->dev->name, pDevice->wpadev->name); | |
147 | unregister_netdev(pDevice->wpadev); | |
148 | free_netdev(pDevice->wpadev); | |
149 | pDevice->wpadev = NULL; | |
150 | } | |
5449c685 FB |
151 | |
152 | return 0; | |
153 | } | |
154 | ||
5449c685 FB |
155 | /* |
156 | * Description: | |
789d1aef | 157 | * Set enable/disable dev for wpa supplicant daemon |
5449c685 FB |
158 | * |
159 | * Parameters: | |
160 | * In: | |
161 | * pDevice - | |
162 | * val - | |
163 | * Out: | |
164 | * | |
165 | * Return Value: | |
166 | * | |
167 | */ | |
168 | ||
169 | int wpa_set_wpadev(PSDevice pDevice, int val) | |
170 | { | |
5449c685 FB |
171 | if (val) |
172 | return wpa_init_wpadev(pDevice); | |
173 | else | |
174 | return wpa_release_wpadev(pDevice); | |
175 | } | |
176 | ||
5449c685 FB |
177 | /* |
178 | * Description: | |
179 | * Set WPA algorithm & keys | |
180 | * | |
181 | * Parameters: | |
182 | * In: | |
183 | * pDevice - | |
184 | * param - | |
185 | * Out: | |
186 | * | |
187 | * Return Value: | |
188 | * | |
189 | */ | |
190 | ||
f2ca407b CC |
191 | int wpa_set_keys(PSDevice pDevice, void *ctx, |
192 | bool fcpfkernel) __must_hold(&pDevice->lock) | |
5449c685 | 193 | { |
f9cf92bf JP |
194 | struct viawget_wpa_param *param = ctx; |
195 | PSMgmtObject pMgmt = pDevice->pMgmt; | |
196 | unsigned long dwKeyIndex = 0; | |
197 | unsigned char abyKey[MAX_KEY_LEN]; | |
198 | unsigned char abySeq[MAX_KEY_LEN]; | |
199 | QWORD KeyRSC; | |
f9cf92bf | 200 | unsigned char byKeyDecMode = KEY_CTL_WEP; |
5449c685 FB |
201 | int ret = 0; |
202 | int uu, ii; | |
203 | ||
6b7200fe | 204 | if (param->u.wpa_key.alg_name > WPA_ALG_CCMP || |
1c5ebaae DC |
205 | param->u.wpa_key.key_len > MAX_KEY_LEN || |
206 | param->u.wpa_key.seq_len > MAX_KEY_LEN) | |
5449c685 FB |
207 | return -EINVAL; |
208 | ||
edd236af | 209 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d\n", param->u.wpa_key.alg_name); |
5449c685 | 210 | if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { |
f9cf92bf JP |
211 | pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; |
212 | pDevice->bEncryptionEnable = false; | |
213 | pDevice->byKeyIndex = 0; | |
214 | pDevice->bTransmitKey = false; | |
215 | KeyvRemoveAllWEPKey(&(pDevice->sKey), pDevice->PortOffset); | |
bc5cf656 | 216 | for (uu = 0; uu < MAX_KEY_TABLE; uu++) |
f9cf92bf | 217 | MACvDisableKeyEntry(pDevice->PortOffset, uu); |
bc5cf656 | 218 | |
f9cf92bf JP |
219 | return ret; |
220 | } | |
5449c685 | 221 | |
f9cf92bf JP |
222 | if (param->u.wpa_key.key && fcpfkernel) { |
223 | memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); | |
5e0cc8a2 | 224 | } else { |
f9cf92bf JP |
225 | spin_unlock_irq(&pDevice->lock); |
226 | if (param->u.wpa_key.key && | |
227 | copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)) { | |
228 | spin_lock_irq(&pDevice->lock); | |
229 | return -EINVAL; | |
230 | } | |
231 | spin_lock_irq(&pDevice->lock); | |
232 | } | |
233 | ||
234 | dwKeyIndex = (unsigned long)(param->u.wpa_key.key_index); | |
5449c685 FB |
235 | |
236 | if (param->u.wpa_key.alg_name == WPA_ALG_WEP) { | |
f9cf92bf JP |
237 | if (dwKeyIndex > 3) { |
238 | return -EINVAL; | |
5e0cc8a2 | 239 | } else { |
f9cf92bf JP |
240 | if (param->u.wpa_key.set_tx) { |
241 | pDevice->byKeyIndex = (unsigned char)dwKeyIndex; | |
242 | pDevice->bTransmitKey = true; | |
243 | dwKeyIndex |= (1 << 31); | |
244 | } | |
245 | KeybSetDefaultKey(&(pDevice->sKey), | |
246 | dwKeyIndex & ~(BIT30 | USE_KEYRSC), | |
247 | param->u.wpa_key.key_len, | |
248 | NULL, | |
249 | abyKey, | |
250 | KEY_CTL_WEP, | |
251 | pDevice->PortOffset, | |
252 | pDevice->byLocalID); | |
253 | ||
254 | } | |
255 | pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; | |
256 | pDevice->bEncryptionEnable = true; | |
257 | return ret; | |
258 | } | |
259 | ||
f9cf92bf JP |
260 | if (param->u.wpa_key.seq && fcpfkernel) { |
261 | memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); | |
5e0cc8a2 | 262 | } else { |
f9cf92bf JP |
263 | spin_unlock_irq(&pDevice->lock); |
264 | if (param->u.wpa_key.seq && | |
265 | copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)) { | |
266 | spin_lock_irq(&pDevice->lock); | |
267 | return -EINVAL; | |
268 | } | |
269 | spin_lock_irq(&pDevice->lock); | |
270 | } | |
5449c685 FB |
271 | |
272 | if (param->u.wpa_key.seq_len > 0) { | |
f9cf92bf JP |
273 | for (ii = 0; ii < param->u.wpa_key.seq_len; ii++) { |
274 | if (ii < 4) | |
275 | LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8)); | |
276 | else | |
277 | HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8)); | |
5449c685 FB |
278 | } |
279 | dwKeyIndex |= 1 << 29; | |
280 | } | |
281 | ||
f9cf92bf JP |
282 | if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { |
283 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n"); | |
284 | return -EINVAL; | |
285 | } | |
5449c685 | 286 | |
bc5cf656 | 287 | if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) |
f9cf92bf | 288 | pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; |
5449c685 | 289 | |
bc5cf656 | 290 | if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) |
f9cf92bf | 291 | pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; |
5449c685 FB |
292 | |
293 | if (param->u.wpa_key.set_tx) | |
294 | dwKeyIndex |= (1 << 31); | |
295 | ||
f9cf92bf JP |
296 | if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) |
297 | byKeyDecMode = KEY_CTL_CCMP; | |
298 | else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) | |
299 | byKeyDecMode = KEY_CTL_TKIP; | |
300 | else | |
301 | byKeyDecMode = KEY_CTL_WEP; | |
302 | ||
303 | // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled | |
304 | if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { | |
305 | if (param->u.wpa_key.key_len == MAX_KEY_LEN) | |
306 | byKeyDecMode = KEY_CTL_TKIP; | |
307 | else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) | |
308 | byKeyDecMode = KEY_CTL_WEP; | |
309 | else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) | |
310 | byKeyDecMode = KEY_CTL_WEP; | |
311 | } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { | |
312 | if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) | |
313 | byKeyDecMode = KEY_CTL_WEP; | |
314 | else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) | |
315 | byKeyDecMode = KEY_CTL_WEP; | |
316 | } | |
317 | ||
318 | // Check TKIP key length | |
319 | if ((byKeyDecMode == KEY_CTL_TKIP) && | |
320 | (param->u.wpa_key.key_len != MAX_KEY_LEN)) { | |
321 | // TKIP Key must be 256 bits | |
f9cf92bf JP |
322 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n"); |
323 | return -EINVAL; | |
324 | } | |
325 | // Check AES key length | |
326 | if ((byKeyDecMode == KEY_CTL_CCMP) && | |
327 | (param->u.wpa_key.key_len != AES_KEY_LEN)) { | |
328 | // AES Key must be 128 bits | |
f9cf92bf JP |
329 | return -EINVAL; |
330 | } | |
331 | ||
332 | // spin_lock_irq(&pDevice->lock); | |
333 | if (is_broadcast_ether_addr(¶m->addr[0]) || (param->addr == NULL)) { | |
334 | // If is_broadcast_ether_addr, set the key as every key entry's group key. | |
335 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); | |
336 | ||
1208f14a | 337 | if (KeybSetAllGroupKey(&(pDevice->sKey), |
f9cf92bf JP |
338 | dwKeyIndex, |
339 | param->u.wpa_key.key_len, | |
340 | (PQWORD) &(KeyRSC), | |
341 | (unsigned char *)abyKey, | |
342 | byKeyDecMode, | |
343 | pDevice->PortOffset, | |
1208f14a TB |
344 | pDevice->byLocalID) && |
345 | KeybSetDefaultKey(&(pDevice->sKey), | |
f9cf92bf JP |
346 | dwKeyIndex, |
347 | param->u.wpa_key.key_len, | |
348 | (PQWORD) &(KeyRSC), | |
349 | (unsigned char *)abyKey, | |
350 | byKeyDecMode, | |
351 | pDevice->PortOffset, | |
1208f14a | 352 | pDevice->byLocalID)) { |
f9cf92bf JP |
353 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); |
354 | ||
355 | } else { | |
f9cf92bf JP |
356 | return -EINVAL; |
357 | } | |
358 | ||
359 | } else { | |
360 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); | |
361 | // BSSID not 0xffffffffffff | |
362 | // Pairwise Key can't be WEP | |
363 | if (byKeyDecMode == KEY_CTL_WEP) { | |
364 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); | |
f9cf92bf JP |
365 | return -EINVAL; |
366 | } | |
367 | ||
368 | dwKeyIndex |= (1 << 30); // set pairwise key | |
4e8a7e5f | 369 | if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) |
f9cf92bf | 370 | return -EINVAL; |
4e8a7e5f | 371 | |
f9cf92bf JP |
372 | if (KeybSetKey(&(pDevice->sKey), |
373 | ¶m->addr[0], | |
374 | dwKeyIndex, | |
375 | param->u.wpa_key.key_len, | |
376 | (PQWORD) &(KeyRSC), | |
377 | (unsigned char *)abyKey, | |
378 | byKeyDecMode, | |
379 | pDevice->PortOffset, | |
1208f14a | 380 | pDevice->byLocalID)) { |
f9cf92bf JP |
381 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); |
382 | ||
383 | } else { | |
384 | // Key Table Full | |
4e8a7e5f | 385 | return -EINVAL; |
f9cf92bf JP |
386 | } |
387 | } // BSSID not 0xffffffffffff | |
388 | if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { | |
389 | pDevice->byKeyIndex = (unsigned char)param->u.wpa_key.key_index; | |
390 | pDevice->bTransmitKey = true; | |
391 | } | |
392 | pDevice->bEncryptionEnable = true; | |
5449c685 FB |
393 | |
394 | return ret; | |
5449c685 FB |
395 | } |
396 | ||
5449c685 FB |
397 | /* |
398 | * Description: | |
399 | * enable wpa auth & mode | |
400 | * | |
401 | * Parameters: | |
402 | * In: | |
403 | * pDevice - | |
404 | * param - | |
405 | * Out: | |
406 | * | |
407 | * Return Value: | |
408 | * | |
409 | */ | |
410 | ||
411 | static int wpa_set_wpa(PSDevice pDevice, | |
f9cf92bf | 412 | struct viawget_wpa_param *param) |
5449c685 | 413 | { |
f9cf92bf | 414 | PSMgmtObject pMgmt = pDevice->pMgmt; |
5449c685 | 415 | |
f9cf92bf JP |
416 | pMgmt->eAuthenMode = WMAC_AUTH_OPEN; |
417 | pMgmt->bShareKeyAlgorithm = false; | |
5449c685 | 418 | |
c804f592 | 419 | return 0; |
5449c685 FB |
420 | } |
421 | ||
f9cf92bf | 422 | /* |
5449c685 FB |
423 | * Description: |
424 | * set disassociate | |
425 | * | |
426 | * Parameters: | |
427 | * In: | |
428 | * pDevice - | |
429 | * param - | |
430 | * Out: | |
431 | * | |
432 | * Return Value: | |
433 | * | |
434 | */ | |
435 | ||
436 | static int wpa_set_disassociate(PSDevice pDevice, | |
f9cf92bf | 437 | struct viawget_wpa_param *param) |
5449c685 | 438 | { |
f9cf92bf | 439 | PSMgmtObject pMgmt = pDevice->pMgmt; |
5449c685 | 440 | |
f9cf92bf JP |
441 | spin_lock_irq(&pDevice->lock); |
442 | if (pDevice->bLinkPass) { | |
443 | if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6)) | |
444 | bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL); | |
445 | } | |
446 | spin_unlock_irq(&pDevice->lock); | |
5449c685 | 447 | |
c804f592 | 448 | return 0; |
5449c685 FB |
449 | } |
450 | ||
5449c685 FB |
451 | /* |
452 | * Description: | |
453 | * enable scan process | |
454 | * | |
455 | * Parameters: | |
456 | * In: | |
457 | * pDevice - | |
458 | * param - | |
459 | * Out: | |
460 | * | |
461 | * Return Value: | |
462 | * | |
463 | */ | |
464 | ||
465 | static int wpa_set_scan(PSDevice pDevice, | |
f9cf92bf | 466 | struct viawget_wpa_param *param) |
5449c685 | 467 | { |
f9cf92bf JP |
468 | spin_lock_irq(&pDevice->lock); |
469 | BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass); | |
470 | bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL); | |
471 | spin_unlock_irq(&pDevice->lock); | |
5449c685 | 472 | |
c804f592 | 473 | return 0; |
5449c685 FB |
474 | } |
475 | ||
5449c685 FB |
476 | /* |
477 | * Description: | |
478 | * get bssid | |
479 | * | |
480 | * Parameters: | |
481 | * In: | |
482 | * pDevice - | |
483 | * param - | |
484 | * Out: | |
485 | * | |
486 | * Return Value: | |
487 | * | |
488 | */ | |
489 | ||
490 | static int wpa_get_bssid(PSDevice pDevice, | |
f9cf92bf | 491 | struct viawget_wpa_param *param) |
5449c685 | 492 | { |
f9cf92bf | 493 | PSMgmtObject pMgmt = pDevice->pMgmt; |
5449c685 FB |
494 | |
495 | memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID , 6); | |
496 | ||
c804f592 | 497 | return 0; |
5449c685 FB |
498 | } |
499 | ||
5449c685 FB |
500 | /* |
501 | * Description: | |
502 | * get bssid | |
503 | * | |
504 | * Parameters: | |
505 | * In: | |
506 | * pDevice - | |
507 | * param - | |
508 | * Out: | |
509 | * | |
510 | * Return Value: | |
511 | * | |
512 | */ | |
513 | ||
514 | static int wpa_get_ssid(PSDevice pDevice, | |
f9cf92bf | 515 | struct viawget_wpa_param *param) |
5449c685 | 516 | { |
f9cf92bf | 517 | PSMgmtObject pMgmt = pDevice->pMgmt; |
5449c685 | 518 | PWLAN_IE_SSID pItemSSID; |
5449c685 | 519 | |
f9cf92bf | 520 | pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; |
5449c685 FB |
521 | |
522 | memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID , pItemSSID->len); | |
523 | param->u.wpa_associate.ssid_len = pItemSSID->len; | |
524 | ||
c804f592 | 525 | return 0; |
5449c685 FB |
526 | } |
527 | ||
5449c685 FB |
528 | /* |
529 | * Description: | |
530 | * get scan results | |
531 | * | |
532 | * Parameters: | |
533 | * In: | |
534 | * pDevice - | |
535 | * param - | |
536 | * Out: | |
537 | * | |
538 | * Return Value: | |
539 | * | |
540 | */ | |
541 | ||
542 | static int wpa_get_scan(PSDevice pDevice, | |
f9cf92bf | 543 | struct viawget_wpa_param *param) |
5449c685 FB |
544 | { |
545 | struct viawget_scan_result *scan_buf; | |
f9cf92bf JP |
546 | PSMgmtObject pMgmt = pDevice->pMgmt; |
547 | PWLAN_IE_SSID pItemSSID; | |
548 | PKnownBSS pBSS; | |
2989e96f | 549 | unsigned char *pBuf; |
5449c685 FB |
550 | int ret = 0; |
551 | u16 count = 0; | |
552 | u16 ii, jj; | |
553 | #if 1 | |
554 | ||
f9cf92bf | 555 | unsigned char *ptempBSS; |
5449c685 | 556 | |
77be4f47 | 557 | ptempBSS = kmalloc(sizeof(KnownBSS), GFP_ATOMIC); |
5449c685 | 558 | |
f9cf92bf | 559 | if (ptempBSS == NULL) { |
edd236af | 560 | printk(KERN_ERR "bubble sort kmalloc memory fail@@@\n"); |
5449c685 | 561 | |
f9cf92bf | 562 | ret = -ENOMEM; |
5449c685 | 563 | |
f9cf92bf | 564 | return ret; |
5449c685 | 565 | |
f9cf92bf | 566 | } |
5449c685 | 567 | |
f9cf92bf | 568 | for (ii = 0; ii < MAX_BSS_NUM; ii++) { |
f9cf92bf | 569 | for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) { |
f9cf92bf | 570 | if ((pMgmt->sBSSList[jj].bActive != true) || |
5449c685 | 571 | |
f9cf92bf | 572 | ((pMgmt->sBSSList[jj].uRSSI > pMgmt->sBSSList[jj + 1].uRSSI) && (pMgmt->sBSSList[jj + 1].bActive != false))) { |
f9cf92bf | 573 | memcpy(ptempBSS, &pMgmt->sBSSList[jj], sizeof(KnownBSS)); |
5449c685 | 574 | |
f9cf92bf | 575 | memcpy(&pMgmt->sBSSList[jj], &pMgmt->sBSSList[jj + 1], sizeof(KnownBSS)); |
5449c685 | 576 | |
f9cf92bf | 577 | memcpy(&pMgmt->sBSSList[jj + 1], ptempBSS, sizeof(KnownBSS)); |
5449c685 | 578 | |
f9cf92bf | 579 | } |
5449c685 | 580 | |
f9cf92bf | 581 | } |
5449c685 | 582 | |
f9cf92bf | 583 | } |
5449c685 | 584 | |
f9cf92bf | 585 | kfree(ptempBSS); |
f9cf92bf | 586 | #endif |
5449c685 FB |
587 | |
588 | //******mike:bubble sort by stronger RSSI*****// | |
589 | ||
5449c685 FB |
590 | count = 0; |
591 | pBSS = &(pMgmt->sBSSList[0]); | |
f9cf92bf JP |
592 | for (ii = 0; ii < MAX_BSS_NUM; ii++) { |
593 | pBSS = &(pMgmt->sBSSList[ii]); | |
594 | if (!pBSS->bActive) | |
595 | continue; | |
596 | count++; | |
597 | } | |
598 | ||
77be4f47 | 599 | pBuf = kcalloc(count, sizeof(struct viawget_scan_result), GFP_ATOMIC); |
f9cf92bf JP |
600 | |
601 | if (pBuf == NULL) { | |
602 | ret = -ENOMEM; | |
603 | return ret; | |
604 | } | |
605 | scan_buf = (struct viawget_scan_result *)pBuf; | |
5449c685 | 606 | pBSS = &(pMgmt->sBSSList[0]); |
f9cf92bf JP |
607 | for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) { |
608 | pBSS = &(pMgmt->sBSSList[ii]); | |
609 | if (pBSS->bActive) { | |
610 | if (jj >= count) | |
611 | break; | |
612 | memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN); | |
613 | pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; | |
614 | memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len); | |
615 | scan_buf->ssid_len = pItemSSID->len; | |
616 | scan_buf->freq = frequency_list[pBSS->uChannel-1]; | |
617 | scan_buf->caps = pBSS->wCapInfo; | |
4e8a7e5f | 618 | |
f9cf92bf JP |
619 | if (pBSS->wWPALen != 0) { |
620 | scan_buf->wpa_ie_len = pBSS->wWPALen; | |
621 | memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen); | |
622 | } | |
623 | if (pBSS->wRSNLen != 0) { | |
624 | scan_buf->rsn_ie_len = pBSS->wRSNLen; | |
625 | memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen); | |
626 | } | |
627 | scan_buf = (struct viawget_scan_result *)((unsigned char *)scan_buf + sizeof(struct viawget_scan_result)); | |
628 | jj++; | |
629 | } | |
630 | } | |
631 | ||
632 | if (jj < count) | |
633 | count = jj; | |
634 | ||
bc5cf656 | 635 | if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) |
5449c685 | 636 | ret = -EFAULT; |
bc5cf656 | 637 | |
5449c685 | 638 | param->u.scan_results.scan_count = count; |
c720dada | 639 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count); |
5449c685 | 640 | |
f9cf92bf JP |
641 | kfree(pBuf); |
642 | return ret; | |
5449c685 FB |
643 | } |
644 | ||
5449c685 FB |
645 | /* |
646 | * Description: | |
647 | * set associate with AP | |
648 | * | |
649 | * Parameters: | |
650 | * In: | |
651 | * pDevice - | |
652 | * param - | |
653 | * Out: | |
654 | * | |
655 | * Return Value: | |
656 | * | |
657 | */ | |
658 | ||
659 | static int wpa_set_associate(PSDevice pDevice, | |
f9cf92bf | 660 | struct viawget_wpa_param *param) |
5449c685 | 661 | { |
f9cf92bf JP |
662 | PSMgmtObject pMgmt = pDevice->pMgmt; |
663 | PWLAN_IE_SSID pItemSSID; | |
664 | unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
665 | unsigned char abyWPAIE[64]; | |
f9cf92bf | 666 | bool bWepEnabled = false; |
5449c685 FB |
667 | |
668 | // set key type & algorithm | |
f9cf92bf JP |
669 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite); |
670 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite); | |
671 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite); | |
672 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg); | |
673 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode); | |
674 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); | |
5449c685 | 675 | |
dd173abf DC |
676 | if (param->u.wpa_associate.wpa_ie_len) { |
677 | if (!param->u.wpa_associate.wpa_ie) | |
678 | return -EINVAL; | |
679 | if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE)) | |
680 | return -EINVAL; | |
681 | if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) | |
682 | return -EFAULT; | |
683 | } | |
5449c685 FB |
684 | |
685 | if (param->u.wpa_associate.mode == 1) | |
f9cf92bf | 686 | pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; |
5449c685 | 687 | else |
f9cf92bf JP |
688 | pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; |
689 | // set ssid | |
5449c685 | 690 | memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); |
f9cf92bf JP |
691 | pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; |
692 | pItemSSID->byElementID = WLAN_EID_SSID; | |
5449c685 FB |
693 | pItemSSID->len = param->u.wpa_associate.ssid_len; |
694 | memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len); | |
695 | // set bssid | |
f9cf92bf JP |
696 | if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0) |
697 | memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6); | |
bc5cf656 | 698 | else |
f9cf92bf | 699 | bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID); |
5449c685 | 700 | |
f9cf92bf JP |
701 | if (param->u.wpa_associate.wpa_ie_len == 0) { |
702 | if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY) | |
703 | pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; | |
704 | else | |
705 | pMgmt->eAuthenMode = WMAC_AUTH_OPEN; | |
5449c685 FB |
706 | } else if (abyWPAIE[0] == RSN_INFO_ELEM) { |
707 | if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) | |
708 | pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; | |
709 | else | |
710 | pMgmt->eAuthenMode = WMAC_AUTH_WPA2; | |
711 | } else { | |
712 | if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE) | |
713 | pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; | |
714 | else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) | |
f9cf92bf | 715 | pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; |
5449c685 | 716 | else |
f9cf92bf | 717 | pMgmt->eAuthenMode = WMAC_AUTH_WPA; |
5449c685 FB |
718 | } |
719 | ||
720 | switch (param->u.wpa_associate.pairwise_suite) { | |
721 | case CIPHER_CCMP: | |
722 | pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; | |
723 | break; | |
724 | case CIPHER_TKIP: | |
725 | pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; | |
726 | break; | |
727 | case CIPHER_WEP40: | |
728 | case CIPHER_WEP104: | |
729 | pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; | |
f9cf92bf | 730 | bWepEnabled = true; |
5449c685 FB |
731 | break; |
732 | case CIPHER_NONE: | |
733 | if (param->u.wpa_associate.group_suite == CIPHER_CCMP) | |
734 | pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; | |
735 | else | |
736 | pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; | |
737 | break; | |
738 | default: | |
739 | pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; | |
95cd17c9 | 740 | } |
5449c685 FB |
741 | |
742 | //DavidWang add for WPA_supplicant support open/share mode | |
743 | ||
f9cf92bf JP |
744 | if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { |
745 | pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; | |
f9cf92bf | 746 | pMgmt->bShareKeyAlgorithm = true; |
5e0cc8a2 | 747 | } else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) { |
f9cf92bf JP |
748 | if (!bWepEnabled) pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; |
749 | else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; | |
f9cf92bf | 750 | } |
5449c685 FB |
751 | //mike save old encryption status |
752 | pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus; | |
753 | ||
f9cf92bf JP |
754 | if (pDevice->eEncryptionStatus != Ndis802_11EncryptionDisabled) |
755 | pDevice->bEncryptionEnable = true; | |
756 | else | |
757 | pDevice->bEncryptionEnable = false; | |
758 | if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) || | |
1208f14a | 759 | ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && bWepEnabled))) //DavidWang //20080717-06,<Modify> by chester//Not to initial WEP |
f9cf92bf JP |
760 | KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); |
761 | spin_lock_irq(&pDevice->lock); | |
762 | pDevice->bLinkPass = false; | |
763 | memset(pMgmt->abyCurrBSSID, 0, 6); | |
764 | pMgmt->eCurrState = WMAC_STATE_IDLE; | |
765 | netif_stop_queue(pDevice->dev); | |
5449c685 FB |
766 | //20080701-02,<Add> by Mike Liu |
767 | /*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/ | |
f9cf92bf JP |
768 | { |
769 | PKnownBSS pCurr = NULL; | |
770 | pCurr = BSSpSearchBSSList(pDevice, | |
771 | pMgmt->abyDesireBSSID, | |
772 | pMgmt->abyDesireSSID, | |
773 | pMgmt->eConfigPHYMode | |
774 | ); | |
775 | ||
776 | if (pCurr == NULL) { | |
777 | printk("wpa_set_associate---->hidden mode site survey before associate.......\n"); | |
778 | bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); | |
779 | } | |
780 | } | |
5449c685 | 781 | /****************************************************************/ |
f9cf92bf JP |
782 | bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); |
783 | spin_unlock_irq(&pDevice->lock); | |
5449c685 | 784 | |
c804f592 | 785 | return 0; |
5449c685 FB |
786 | } |
787 | ||
5449c685 FB |
788 | /* |
789 | * Description: | |
790 | * wpa_ioctl main function supported for wpa supplicant | |
791 | * | |
792 | * Parameters: | |
793 | * In: | |
794 | * pDevice - | |
795 | * iw_point - | |
796 | * Out: | |
797 | * | |
798 | * Return Value: | |
799 | * | |
800 | */ | |
801 | ||
802 | int wpa_ioctl(PSDevice pDevice, struct iw_point *p) | |
803 | { | |
804 | struct viawget_wpa_param *param; | |
805 | int ret = 0; | |
806 | int wpa_ioctl = 0; | |
807 | ||
808 | if (p->length < sizeof(struct viawget_wpa_param) || | |
809 | p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer) | |
810 | return -EINVAL; | |
811 | ||
77be4f47 | 812 | param = kmalloc((int)p->length, GFP_KERNEL); |
5449c685 FB |
813 | if (param == NULL) |
814 | return -ENOMEM; | |
815 | ||
816 | if (copy_from_user(param, p->pointer, p->length)) { | |
817 | ret = -EFAULT; | |
818 | goto out; | |
819 | } | |
820 | ||
821 | switch (param->cmd) { | |
822 | case VIAWGET_SET_WPA: | |
f9cf92bf | 823 | ret = wpa_set_wpa(pDevice, param); |
edd236af | 824 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA\n"); |
5449c685 FB |
825 | break; |
826 | ||
827 | case VIAWGET_SET_KEY: | |
edd236af | 828 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY\n"); |
f9cf92bf JP |
829 | spin_lock_irq(&pDevice->lock); |
830 | ret = wpa_set_keys(pDevice, param, false); | |
831 | spin_unlock_irq(&pDevice->lock); | |
5449c685 FB |
832 | break; |
833 | ||
834 | case VIAWGET_SET_SCAN: | |
edd236af | 835 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN\n"); |
f9cf92bf | 836 | ret = wpa_set_scan(pDevice, param); |
5449c685 FB |
837 | break; |
838 | ||
839 | case VIAWGET_GET_SCAN: | |
f9cf92bf JP |
840 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n"); |
841 | ret = wpa_get_scan(pDevice, param); | |
5449c685 FB |
842 | wpa_ioctl = 1; |
843 | break; | |
844 | ||
845 | case VIAWGET_GET_SSID: | |
edd236af | 846 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID\n"); |
f9cf92bf | 847 | ret = wpa_get_ssid(pDevice, param); |
5449c685 FB |
848 | wpa_ioctl = 1; |
849 | break; | |
850 | ||
851 | case VIAWGET_GET_BSSID: | |
edd236af | 852 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID\n"); |
f9cf92bf | 853 | ret = wpa_get_bssid(pDevice, param); |
5449c685 FB |
854 | wpa_ioctl = 1; |
855 | break; | |
856 | ||
857 | case VIAWGET_SET_ASSOCIATE: | |
edd236af | 858 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE\n"); |
f9cf92bf | 859 | ret = wpa_set_associate(pDevice, param); |
5449c685 FB |
860 | break; |
861 | ||
862 | case VIAWGET_SET_DISASSOCIATE: | |
edd236af | 863 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE\n"); |
f9cf92bf | 864 | ret = wpa_set_disassociate(pDevice, param); |
5449c685 FB |
865 | break; |
866 | ||
867 | case VIAWGET_SET_DROP_UNENCRYPT: | |
edd236af | 868 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT\n"); |
5449c685 FB |
869 | break; |
870 | ||
f9cf92bf | 871 | case VIAWGET_SET_DEAUTHENTICATE: |
edd236af | 872 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE\n"); |
5449c685 FB |
873 | break; |
874 | ||
875 | default: | |
f9cf92bf JP |
876 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n", |
877 | param->cmd); | |
6d239874 CE |
878 | ret = -EOPNOTSUPP; |
879 | goto out; | |
5449c685 FB |
880 | } |
881 | ||
882 | if ((ret == 0) && wpa_ioctl) { | |
883 | if (copy_to_user(p->pointer, param, p->length)) { | |
884 | ret = -EFAULT; | |
885 | goto out; | |
886 | } | |
887 | } | |
888 | ||
889 | out: | |
6403bb7d | 890 | kfree(param); |
5449c685 FB |
891 | |
892 | return ret; | |
893 | } |