Commit | Line | Data |
---|---|---|
92b96797 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 | * | |
19 | * File: dpc.c | |
20 | * | |
21 | * Purpose: handle dpc rx functions | |
22 | * | |
23 | * Author: Lyndon Chen | |
24 | * | |
25 | * Date: May 20, 2003 | |
26 | * | |
27 | * Functions: | |
28 | * device_receive_frame - Rcv 802.11 frame function | |
92b96797 | 29 | * s_bHandleRxEncryption- Rcv decrypted data via on-fly |
92b96797 FB |
30 | * s_byGetRateIdx- get rate index |
31 | * s_vGetDASA- get data offset | |
32 | * s_vProcessRxMACHeader- Rcv 802.11 and translate to 802.3 | |
33 | * | |
34 | * Revision History: | |
35 | * | |
36 | */ | |
37 | ||
d820fa95 | 38 | #include "dpc.h" |
92b96797 | 39 | #include "device.h" |
92b96797 | 40 | #include "rxtx.h" |
92b96797 | 41 | #include "tether.h" |
92b96797 | 42 | #include "card.h" |
92b96797 | 43 | #include "bssdb.h" |
92b96797 | 44 | #include "mac.h" |
92b96797 | 45 | #include "baseband.h" |
92b96797 | 46 | #include "michael.h" |
92b96797 | 47 | #include "tkip.h" |
92b96797 | 48 | #include "wctl.h" |
92b96797 | 49 | #include "rf.h" |
92b96797 | 50 | #include "iowpa.h" |
92b96797 | 51 | #include "datarate.h" |
92b96797 | 52 | #include "usbpipe.h" |
92b96797 | 53 | |
92b96797 FB |
54 | //static int msglevel =MSG_LEVEL_DEBUG; |
55 | static int msglevel =MSG_LEVEL_INFO; | |
56 | ||
3b138851 | 57 | static const u8 acbyRxRate[MAX_RATE] = |
92b96797 FB |
58 | {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; |
59 | ||
b902fbfe | 60 | static u8 s_byGetRateIdx(u8 byRate); |
92b96797 FB |
61 | |
62 | static | |
8611a29a | 63 | void |
92b96797 | 64 | s_vGetDASA( |
b902fbfe | 65 | u8 * pbyRxBufferAddr, |
93a94c42 | 66 | unsigned int *pcbHeaderSize, |
ceb8c5da | 67 | struct ethhdr *psEthHeader |
92b96797 FB |
68 | ); |
69 | ||
45c73bb1 MP |
70 | static void s_vProcessRxMACHeader(struct vnt_private *pDevice, |
71 | u8 *pbyRxBufferAddr, u32 cbPacketSize, int bIsWEP, int bExtIV, | |
72 | u32 *pcbHeadSize); | |
92b96797 | 73 | |
45c73bb1 MP |
74 | static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame, |
75 | u32 FrameSize, u8 *pbyRsr, u8 *pbyNewRsr, PSKeyItem *pKeyOut, | |
76 | s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16); | |
92b96797 | 77 | |
92b96797 FB |
78 | /*+ |
79 | * | |
80 | * Description: | |
81 | * Translate Rcv 802.11 header to 802.3 header with Rx buffer | |
82 | * | |
83 | * Parameters: | |
84 | * In: | |
85 | * pDevice | |
86 | * dwRxBufferAddr - Address of Rcv Buffer | |
87 | * cbPacketSize - Rcv Packet size | |
88 | * bIsWEP - If Rcv with WEP | |
89 | * Out: | |
90 | * pcbHeaderSize - 802.11 header size | |
91 | * | |
92 | * Return Value: None | |
93 | * | |
94 | -*/ | |
45c73bb1 MP |
95 | |
96 | static void s_vProcessRxMACHeader(struct vnt_private *pDevice, | |
97 | u8 *pbyRxBufferAddr, u32 cbPacketSize, int bIsWEP, int bExtIV, | |
98 | u32 *pcbHeadSize) | |
92b96797 | 99 | { |
45c73bb1 MP |
100 | u8 *pbyRxBuffer; |
101 | u32 cbHeaderSize = 0; | |
102 | u16 *pwType; | |
1cac4a4b | 103 | struct ieee80211_hdr *pMACHeader; |
45c73bb1 | 104 | int ii; |
92b96797 | 105 | |
1cac4a4b | 106 | pMACHeader = (struct ieee80211_hdr *) (pbyRxBufferAddr + cbHeaderSize); |
92b96797 | 107 | |
b902fbfe | 108 | s_vGetDASA((u8 *)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader); |
92b96797 FB |
109 | |
110 | if (bIsWEP) { | |
111 | if (bExtIV) { | |
112 | // strip IV&ExtIV , add 8 byte | |
113 | cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 8); | |
114 | } else { | |
115 | // strip IV , add 4 byte | |
116 | cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 4); | |
117 | } | |
118 | } | |
119 | else { | |
120 | cbHeaderSize += WLAN_HDR_ADDR3_LEN; | |
121 | }; | |
122 | ||
b902fbfe | 123 | pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize); |
8329419a | 124 | if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_Bridgetunnel)) { |
92b96797 | 125 | cbHeaderSize += 6; |
8329419a | 126 | } else if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_RFC1042)) { |
92b96797 | 127 | cbHeaderSize += 6; |
3eaca0d2 | 128 | pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); |
aa209eef | 129 | if ((*pwType == cpu_to_be16(ETH_P_IPX)) || |
203e4615 AM |
130 | (*pwType == cpu_to_le16(0xF380))) { |
131 | cbHeaderSize -= 8; | |
3eaca0d2 | 132 | pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); |
92b96797 FB |
133 | if (bIsWEP) { |
134 | if (bExtIV) { | |
135 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV | |
136 | } else { | |
137 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV | |
138 | } | |
139 | } | |
140 | else { | |
141 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); | |
142 | } | |
143 | } | |
144 | } | |
145 | else { | |
146 | cbHeaderSize -= 2; | |
3eaca0d2 | 147 | pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); |
92b96797 FB |
148 | if (bIsWEP) { |
149 | if (bExtIV) { | |
150 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV | |
151 | } else { | |
152 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV | |
153 | } | |
154 | } | |
155 | else { | |
156 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); | |
157 | } | |
158 | } | |
159 | ||
9a0e756c | 160 | cbHeaderSize -= (ETH_ALEN * 2); |
b902fbfe | 161 | pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize); |
9a0e756c | 162 | for (ii = 0; ii < ETH_ALEN; ii++) |
ceb8c5da | 163 | *pbyRxBuffer++ = pDevice->sRxEthHeader.h_dest[ii]; |
9a0e756c | 164 | for (ii = 0; ii < ETH_ALEN; ii++) |
ceb8c5da | 165 | *pbyRxBuffer++ = pDevice->sRxEthHeader.h_source[ii]; |
92b96797 FB |
166 | |
167 | *pcbHeadSize = cbHeaderSize; | |
168 | } | |
169 | ||
b902fbfe | 170 | static u8 s_byGetRateIdx(u8 byRate) |
92b96797 | 171 | { |
b902fbfe | 172 | u8 byRateIdx; |
92b96797 FB |
173 | |
174 | for (byRateIdx = 0; byRateIdx <MAX_RATE ; byRateIdx++) { | |
175 | if (acbyRxRate[byRateIdx%MAX_RATE] == byRate) | |
176 | return byRateIdx; | |
177 | } | |
178 | return 0; | |
179 | } | |
180 | ||
92b96797 | 181 | static |
8611a29a | 182 | void |
92b96797 | 183 | s_vGetDASA ( |
b902fbfe | 184 | u8 * pbyRxBufferAddr, |
93a94c42 | 185 | unsigned int *pcbHeaderSize, |
ceb8c5da | 186 | struct ethhdr *psEthHeader |
92b96797 FB |
187 | ) |
188 | { | |
cc856e61 | 189 | unsigned int cbHeaderSize = 0; |
1cac4a4b | 190 | struct ieee80211_hdr *pMACHeader; |
9a0e756c AM |
191 | int ii; |
192 | ||
1cac4a4b | 193 | pMACHeader = (struct ieee80211_hdr *) (pbyRxBufferAddr + cbHeaderSize); |
9a0e756c | 194 | |
1cac4a4b AM |
195 | if ((pMACHeader->frame_control & FC_TODS) == 0) { |
196 | if (pMACHeader->frame_control & FC_FROMDS) { | |
9a0e756c | 197 | for (ii = 0; ii < ETH_ALEN; ii++) { |
ceb8c5da | 198 | psEthHeader->h_dest[ii] = |
1cac4a4b | 199 | pMACHeader->addr1[ii]; |
ceb8c5da | 200 | psEthHeader->h_source[ii] = |
1cac4a4b | 201 | pMACHeader->addr3[ii]; |
9a0e756c AM |
202 | } |
203 | } else { | |
204 | /* IBSS mode */ | |
205 | for (ii = 0; ii < ETH_ALEN; ii++) { | |
ceb8c5da | 206 | psEthHeader->h_dest[ii] = |
1cac4a4b | 207 | pMACHeader->addr1[ii]; |
ceb8c5da | 208 | psEthHeader->h_source[ii] = |
1cac4a4b | 209 | pMACHeader->addr2[ii]; |
9a0e756c AM |
210 | } |
211 | } | |
212 | } else { | |
213 | /* Is AP mode.. */ | |
1cac4a4b | 214 | if (pMACHeader->frame_control & FC_FROMDS) { |
9a0e756c | 215 | for (ii = 0; ii < ETH_ALEN; ii++) { |
ceb8c5da | 216 | psEthHeader->h_dest[ii] = |
1cac4a4b | 217 | pMACHeader->addr3[ii]; |
ceb8c5da | 218 | psEthHeader->h_source[ii] = |
1cac4a4b | 219 | pMACHeader->addr4[ii]; |
9a0e756c AM |
220 | cbHeaderSize += 6; |
221 | } | |
222 | } else { | |
223 | for (ii = 0; ii < ETH_ALEN; ii++) { | |
ceb8c5da | 224 | psEthHeader->h_dest[ii] = |
1cac4a4b | 225 | pMACHeader->addr3[ii]; |
ceb8c5da | 226 | psEthHeader->h_source[ii] = |
1cac4a4b | 227 | pMACHeader->addr2[ii]; |
9a0e756c AM |
228 | } |
229 | } | |
230 | }; | |
92b96797 FB |
231 | *pcbHeaderSize = cbHeaderSize; |
232 | } | |
233 | ||
115cac2e | 234 | int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB, |
45c73bb1 | 235 | unsigned long BytesToIndicate) |
92b96797 | 236 | { |
45c73bb1 MP |
237 | struct net_device_stats *pStats = &pDevice->stats; |
238 | struct sk_buff *skb; | |
239 | struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; | |
240 | struct vnt_rx_mgmt *pRxPacket = &pMgmt->sRxPacket; | |
1cac4a4b | 241 | struct ieee80211_hdr *p802_11Header; |
45c73bb1 | 242 | u8 *pbyRsr, *pbyNewRsr, *pbyRSSI, *pbyFrame; |
7c65fa2a | 243 | u64 *pqwTSFTime; |
e269fc2d | 244 | u32 bDeFragRx = false; |
45c73bb1 | 245 | u32 cbHeaderOffset, cbIVOffset; |
cf5d170e | 246 | u32 FrameSize; |
45c73bb1 | 247 | u16 wEtherType = 0; |
c0fcac91 | 248 | s32 iSANodeIndex = -1; |
45c73bb1 MP |
249 | int ii; |
250 | u8 *pbyRxSts, *pbyRxRate, *pbySQ, *pby3SQ; | |
251 | u32 cbHeaderSize; | |
252 | PSKeyItem pKey = NULL; | |
253 | u16 wRxTSC15_0 = 0; | |
254 | u32 dwRxTSC47_16 = 0; | |
45c73bb1 | 255 | /* signed long ldBm = 0; */ |
e269fc2d | 256 | int bIsWEP = false; int bExtIV = false; |
cf5d170e | 257 | u32 dwWbkStatus; |
115cac2e | 258 | struct vnt_rcb *pRCBIndicate = pRCB; |
45c73bb1 MP |
259 | u8 *pbyDAddress; |
260 | u16 *pwPLCP_Length; | |
261 | u8 abyVaildRate[MAX_RATE] | |
262 | = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; | |
263 | u16 wPLCPwithPadding; | |
1cac4a4b | 264 | struct ieee80211_hdr *pMACHeader; |
e269fc2d | 265 | int bRxeapol_key = false; |
92b96797 | 266 | |
92b96797 FB |
267 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- RXbBulkInProcessData---\n"); |
268 | ||
269 | skb = pRCB->skb; | |
270 | ||
cf5d170e MP |
271 | /* [31:16]RcvByteCount ( not include 4-byte Status ) */ |
272 | dwWbkStatus = *((u32 *)(skb->data)); | |
273 | FrameSize = dwWbkStatus >> 16; | |
274 | FrameSize += 4; | |
92b96797 | 275 | |
cf5d170e MP |
276 | if (BytesToIndicate != FrameSize) { |
277 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"------- WRONG Length 1\n"); | |
9a450f9a | 278 | pStats->rx_frame_errors++; |
e269fc2d | 279 | return false; |
cf5d170e | 280 | } |
92b96797 | 281 | |
bd2bc4c7 | 282 | if ((BytesToIndicate > 2372) || (BytesToIndicate <= 40)) { |
92b96797 | 283 | // Frame Size error drop this packet. |
bd2bc4c7 | 284 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 2\n"); |
9a450f9a | 285 | pStats->rx_frame_errors++; |
e269fc2d | 286 | return false; |
92b96797 FB |
287 | } |
288 | ||
b902fbfe | 289 | pbyDAddress = (u8 *)(skb->data); |
92b96797 FB |
290 | pbyRxSts = pbyDAddress+4; |
291 | pbyRxRate = pbyDAddress+5; | |
292 | ||
293 | //real Frame Size = USBFrameSize -4WbkStatus - 4RxStatus - 8TSF - 4RSR - 4SQ3 - ?Padding | |
294 | //if SQ3 the range is 24~27, if no SQ3 the range is 20~23 | |
295 | //real Frame size in PLCPLength field. | |
3eaca0d2 | 296 | pwPLCP_Length = (u16 *) (pbyDAddress + 6); |
92b96797 FB |
297 | //Fix hardware bug => PLCP_Length error |
298 | if ( ((BytesToIndicate - (*pwPLCP_Length)) > 27) || | |
299 | ((BytesToIndicate - (*pwPLCP_Length)) < 24) || | |
300 | (BytesToIndicate < (*pwPLCP_Length)) ) { | |
301 | ||
302 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong PLCP Length %x\n", (int) *pwPLCP_Length); | |
9a450f9a | 303 | pStats->rx_frame_errors++; |
e269fc2d | 304 | return false; |
92b96797 FB |
305 | } |
306 | for ( ii=RATE_1M;ii<MAX_RATE;ii++) { | |
307 | if ( *pbyRxRate == abyVaildRate[ii] ) { | |
308 | break; | |
309 | } | |
310 | } | |
311 | if ( ii==MAX_RATE ) { | |
312 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong RxRate %x\n",(int) *pbyRxRate); | |
e269fc2d | 313 | return false; |
92b96797 FB |
314 | } |
315 | ||
316 | wPLCPwithPadding = ( (*pwPLCP_Length / 4) + ( (*pwPLCP_Length % 4) ? 1:0 ) ) *4; | |
317 | ||
7c65fa2a | 318 | pqwTSFTime = (u64 *)(pbyDAddress + 8 + wPLCPwithPadding); |
92b96797 FB |
319 | if(pDevice->byBBType == BB_TYPE_11G) { |
320 | pby3SQ = pbyDAddress + 8 + wPLCPwithPadding + 12; | |
321 | pbySQ = pby3SQ; | |
322 | } | |
323 | else { | |
324 | pbySQ = pbyDAddress + 8 + wPLCPwithPadding + 8; | |
325 | pby3SQ = pbySQ; | |
326 | } | |
92b96797 FB |
327 | pbyNewRsr = pbyDAddress + 8 + wPLCPwithPadding + 9; |
328 | pbyRSSI = pbyDAddress + 8 + wPLCPwithPadding + 10; | |
329 | pbyRsr = pbyDAddress + 8 + wPLCPwithPadding + 11; | |
330 | ||
331 | FrameSize = *pwPLCP_Length; | |
332 | ||
333 | pbyFrame = pbyDAddress + 8; | |
92b96797 | 334 | |
1cac4a4b | 335 | pMACHeader = (struct ieee80211_hdr *) pbyFrame; |
92b96797 FB |
336 | |
337 | //mike add: to judge if current AP is activated? | |
338 | if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) || | |
339 | (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) { | |
340 | if (pMgmt->sNodeDBTable[0].bActive) { | |
8329419a | 341 | if (ether_addr_equal(pMgmt->abyCurrBSSID, pMACHeader->addr2)) { |
92b96797 FB |
342 | if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) |
343 | pMgmt->sNodeDBTable[0].uInActiveCount = 0; | |
344 | } | |
345 | } | |
346 | } | |
347 | ||
1cac4a4b AM |
348 | if (!is_multicast_ether_addr(pMACHeader->addr1)) { |
349 | if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (struct ieee80211_hdr *) pbyFrame)) { | |
e269fc2d | 350 | return false; |
92b96797 FB |
351 | } |
352 | ||
8329419a | 353 | if (!ether_addr_equal(pDevice->abyCurrentNetAddr, pMACHeader->addr1)) { |
e269fc2d | 354 | return false; |
92b96797 FB |
355 | } |
356 | } | |
357 | ||
92b96797 FB |
358 | // Use for TKIP MIC |
359 | s_vGetDASA(pbyFrame, &cbHeaderSize, &pDevice->sRxEthHeader); | |
360 | ||
8329419a JP |
361 | if (ether_addr_equal((u8 *)pDevice->sRxEthHeader.h_source, |
362 | pDevice->abyCurrentNetAddr)) | |
e269fc2d | 363 | return false; |
92b96797 FB |
364 | |
365 | if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { | |
366 | if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { | |
1cac4a4b | 367 | p802_11Header = (struct ieee80211_hdr *) (pbyFrame); |
92b96797 | 368 | // get SA NodeIndex |
1cac4a4b | 369 | if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(p802_11Header->addr2), &iSANodeIndex)) { |
92b96797 FB |
370 | pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies; |
371 | pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0; | |
372 | } | |
373 | } | |
374 | } | |
375 | ||
92b96797 | 376 | if (IS_FC_WEP(pbyFrame)) { |
e269fc2d | 377 | bool bRxDecryOK = false; |
92b96797 FB |
378 | |
379 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rx WEP pkt\n"); | |
4e9b5e2b | 380 | bIsWEP = true; |
90f96acd MP |
381 | |
382 | bRxDecryOK = s_bHandleRxEncryption(pDevice, pbyFrame, FrameSize, | |
383 | pbyRsr, pbyNewRsr, &pKey, &bExtIV, &wRxTSC15_0, &dwRxTSC47_16); | |
92b96797 FB |
384 | |
385 | if (bRxDecryOK) { | |
386 | if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) { | |
387 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV Fail\n"); | |
388 | if ( (pMgmt->eAuthenMode == WMAC_AUTH_WPA) || | |
389 | (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || | |
390 | (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || | |
391 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || | |
392 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { | |
92b96797 | 393 | } |
e269fc2d | 394 | return false; |
92b96797 FB |
395 | } |
396 | } else { | |
397 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WEP Func Fail\n"); | |
e269fc2d | 398 | return false; |
92b96797 FB |
399 | } |
400 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) | |
401 | FrameSize -= 8; // Message Integrity Code | |
402 | else | |
403 | FrameSize -= 4; // 4 is ICV | |
404 | } | |
405 | ||
92b96797 FB |
406 | // |
407 | // RX OK | |
408 | // | |
abad19d0 AM |
409 | /* remove the FCS/CRC length */ |
410 | FrameSize -= ETH_FCS_LEN; | |
92b96797 | 411 | |
8a3d91b0 | 412 | if ( !(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) && // unicast address |
92b96797 FB |
413 | (IS_FRAGMENT_PKT((pbyFrame))) |
414 | ) { | |
415 | // defragment | |
1cac4a4b | 416 | bDeFragRx = WCTLbHandleFragment(pDevice, (struct ieee80211_hdr *) (pbyFrame), FrameSize, bIsWEP, bExtIV); |
92b96797 FB |
417 | if (bDeFragRx) { |
418 | // defrag complete | |
419 | // TODO skb, pbyFrame | |
420 | skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb; | |
421 | FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength; | |
422 | pbyFrame = skb->data + 8; | |
423 | } | |
424 | else { | |
e269fc2d | 425 | return false; |
92b96797 FB |
426 | } |
427 | } | |
428 | ||
429 | // | |
430 | // Management & Control frame Handle | |
431 | // | |
e269fc2d | 432 | if ((IS_TYPE_DATA((pbyFrame))) == false) { |
92b96797 FB |
433 | // Handle Control & Manage Frame |
434 | ||
435 | if (IS_TYPE_MGMT((pbyFrame))) { | |
b902fbfe AM |
436 | u8 * pbyData1; |
437 | u8 * pbyData2; | |
92b96797 FB |
438 | |
439 | pRxPacket = &(pRCB->sMngPacket); | |
440 | pRxPacket->p80211Header = (PUWLAN_80211HDR)(pbyFrame); | |
441 | pRxPacket->cbMPDULen = FrameSize; | |
442 | pRxPacket->uRSSI = *pbyRSSI; | |
443 | pRxPacket->bySQ = *pbySQ; | |
7c65fa2a | 444 | pRxPacket->qwLocalTSF = cpu_to_le64(*pqwTSFTime); |
92b96797 FB |
445 | if (bIsWEP) { |
446 | // strip IV | |
447 | pbyData1 = WLAN_HDR_A3_DATA_PTR(pbyFrame); | |
448 | pbyData2 = WLAN_HDR_A3_DATA_PTR(pbyFrame) + 4; | |
449 | for (ii = 0; ii < (FrameSize - 4); ii++) { | |
450 | *pbyData1 = *pbyData2; | |
451 | pbyData1++; | |
452 | pbyData2++; | |
453 | } | |
454 | } | |
455 | ||
456 | pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate); | |
457 | ||
458 | if ( *pbyRxSts == 0 ) { | |
459 | //Discard beacon packet which channel is 0 | |
460 | if ( (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_BEACON) || | |
461 | (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_PROBERESP) ) { | |
e269fc2d | 462 | return false; |
92b96797 FB |
463 | } |
464 | } | |
465 | pRxPacket->byRxChannel = (*pbyRxSts) >> 2; | |
466 | ||
92b96797 FB |
467 | // |
468 | // Insert the RCB in the Recv Mng list | |
469 | // | |
470 | EnqueueRCB(pDevice->FirstRecvMngList, pDevice->LastRecvMngList, pRCBIndicate); | |
471 | pDevice->NumRecvMngList++; | |
e269fc2d | 472 | if ( bDeFragRx == false) { |
92b96797 FB |
473 | pRCB->Ref++; |
474 | } | |
e269fc2d | 475 | if (pDevice->bIsRxMngWorkItemQueued == false) { |
4e9b5e2b | 476 | pDevice->bIsRxMngWorkItemQueued = true; |
a21fc2f5 | 477 | schedule_work(&pDevice->rx_mng_work_item); |
92b96797 FB |
478 | } |
479 | ||
480 | } | |
481 | else { | |
482 | // Control Frame | |
483 | }; | |
e269fc2d | 484 | return false; |
92b96797 FB |
485 | } |
486 | else { | |
487 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { | |
488 | //In AP mode, hw only check addr1(BSSID or RA) if equal to local MAC. | |
8a3d91b0 | 489 | if ( !(*pbyRsr & RSR_BSSIDOK)) { |
92b96797 FB |
490 | if (bDeFragRx) { |
491 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
492 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
493 | pDevice->dev->name); | |
494 | } | |
495 | } | |
e269fc2d | 496 | return false; |
92b96797 FB |
497 | } |
498 | } | |
499 | else { | |
500 | // discard DATA packet while not associate || BSSID error | |
e269fc2d | 501 | if ((pDevice->bLinkPass == false) || |
8a3d91b0 | 502 | !(*pbyRsr & RSR_BSSIDOK)) { |
92b96797 FB |
503 | if (bDeFragRx) { |
504 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
505 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
506 | pDevice->dev->name); | |
507 | } | |
508 | } | |
e269fc2d | 509 | return false; |
92b96797 FB |
510 | } |
511 | //mike add:station mode check eapol-key challenge---> | |
512 | { | |
b902fbfe AM |
513 | u8 Protocol_Version; //802.1x Authentication |
514 | u8 Packet_Type; //802.1x Authentication | |
515 | u8 Descriptor_type; | |
3eaca0d2 | 516 | u16 Key_info; |
92b96797 FB |
517 | if (bIsWEP) |
518 | cbIVOffset = 8; | |
519 | else | |
520 | cbIVOffset = 0; | |
521 | wEtherType = (skb->data[cbIVOffset + 8 + 24 + 6] << 8) | | |
522 | skb->data[cbIVOffset + 8 + 24 + 6 + 1]; | |
523 | Protocol_Version = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1]; | |
524 | Packet_Type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1]; | |
525 | if (wEtherType == ETH_P_PAE) { //Protocol Type in LLC-Header | |
526 | if(((Protocol_Version==1) ||(Protocol_Version==2)) && | |
527 | (Packet_Type==3)) { //802.1x OR eapol-key challenge frame receive | |
4e9b5e2b | 528 | bRxeapol_key = true; |
92b96797 FB |
529 | Descriptor_type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2]; |
530 | Key_info = (skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2+1]<<8) |skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2+2] ; | |
531 | if(Descriptor_type==2) { //RSN | |
532 | // printk("WPA2_Rx_eapol-key_info<-----:%x\n",Key_info); | |
533 | } | |
534 | else if(Descriptor_type==254) { | |
535 | // printk("WPA_Rx_eapol-key_info<-----:%x\n",Key_info); | |
536 | } | |
537 | } | |
538 | } | |
539 | } | |
540 | //mike add:station mode check eapol-key challenge<--- | |
541 | } | |
542 | } | |
543 | ||
92b96797 FB |
544 | // Data frame Handle |
545 | ||
92b96797 FB |
546 | if (pDevice->bEnablePSMode) { |
547 | if (IS_FC_MOREDATA((pbyFrame))) { | |
8a3d91b0 | 548 | if (*pbyRsr & RSR_ADDROK) { |
92b96797 FB |
549 | //PSbSendPSPOLL((PSDevice)pDevice); |
550 | } | |
551 | } | |
552 | else { | |
4e9b5e2b | 553 | if (pMgmt->bInTIMWake == true) { |
e269fc2d | 554 | pMgmt->bInTIMWake = false; |
92b96797 FB |
555 | } |
556 | } | |
9fc86028 | 557 | } |
92b96797 | 558 | |
92b96797 FB |
559 | // ++++++++ For BaseBand Algorithm +++++++++++++++ |
560 | pDevice->uCurrRSSI = *pbyRSSI; | |
561 | pDevice->byCurrSQ = *pbySQ; | |
562 | ||
563 | // todo | |
564 | /* | |
565 | if ((*pbyRSSI != 0) && | |
566 | (pMgmt->pCurrBSS!=NULL)) { | |
567 | RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); | |
a0a1f61a | 568 | // Monitor if RSSI is too strong. |
92b96797 FB |
569 | pMgmt->pCurrBSS->byRSSIStatCnt++; |
570 | pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT; | |
571 | pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm; | |
33d33e42 AM |
572 | for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { |
573 | if (pMgmt->pCurrBSS->ldBmAverage[ii] != 0) { | |
574 | pMgmt->pCurrBSS->ldBmMAX = | |
575 | max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm); | |
576 | } | |
92b96797 FB |
577 | } |
578 | } | |
579 | */ | |
580 | ||
92b96797 FB |
581 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { |
582 | if (bIsWEP) { | |
583 | FrameSize -= 8; //MIC | |
584 | } | |
585 | } | |
586 | ||
587 | //-------------------------------------------------------------------------------- | |
588 | // Soft MIC | |
589 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { | |
590 | if (bIsWEP) { | |
52a7e64b AM |
591 | u32 * pdwMIC_L; |
592 | u32 * pdwMIC_R; | |
593 | u32 dwMIC_Priority; | |
594 | u32 dwMICKey0 = 0, dwMICKey1 = 0; | |
595 | u32 dwLocalMIC_L = 0; | |
596 | u32 dwLocalMIC_R = 0; | |
92b96797 | 597 | |
92b96797 | 598 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { |
52a7e64b AM |
599 | dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[24])); |
600 | dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[28])); | |
92b96797 FB |
601 | } |
602 | else { | |
603 | if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { | |
52a7e64b AM |
604 | dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[16])); |
605 | dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[20])); | |
92b96797 | 606 | } else if ((pKey->dwKeyIndex & BIT28) == 0) { |
52a7e64b AM |
607 | dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[16])); |
608 | dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[20])); | |
92b96797 | 609 | } else { |
52a7e64b AM |
610 | dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[24])); |
611 | dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[28])); | |
92b96797 FB |
612 | } |
613 | } | |
614 | ||
615 | MIC_vInit(dwMICKey0, dwMICKey1); | |
ceb8c5da | 616 | MIC_vAppend((u8 *)&(pDevice->sRxEthHeader.h_dest[0]), 12); |
92b96797 | 617 | dwMIC_Priority = 0; |
b902fbfe | 618 | MIC_vAppend((u8 *)&dwMIC_Priority, 4); |
92b96797 | 619 | // 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV. |
b902fbfe | 620 | MIC_vAppend((u8 *)(skb->data + 8 + WLAN_HDR_ADDR3_LEN + 8), |
92b96797 FB |
621 | FrameSize - WLAN_HDR_ADDR3_LEN - 8); |
622 | MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R); | |
623 | MIC_vUnInit(); | |
624 | ||
52a7e64b AM |
625 | pdwMIC_L = (u32 *)(skb->data + 8 + FrameSize); |
626 | pdwMIC_R = (u32 *)(skb->data + 8 + FrameSize + 4); | |
92b96797 | 627 | |
92b96797 | 628 | if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) || |
4e9b5e2b | 629 | (pDevice->bRxMICFail == true)) { |
92b96797 | 630 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC comparison is fail!\n"); |
e269fc2d | 631 | pDevice->bRxMICFail = false; |
92b96797 FB |
632 | if (bDeFragRx) { |
633 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
634 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
635 | pDevice->dev->name); | |
636 | } | |
637 | } | |
92b96797 | 638 | //send event to wpa_supplicant |
4e9b5e2b | 639 | //if(pDevice->bWPASuppWextEnabled == true) |
92b96797 FB |
640 | { |
641 | union iwreq_data wrqu; | |
642 | struct iw_michaelmicfailure ev; | |
643 | int keyidx = pbyFrame[cbHeaderSize+3] >> 6; //top two-bits | |
644 | memset(&ev, 0, sizeof(ev)); | |
645 | ev.flags = keyidx & IW_MICFAILURE_KEY_ID; | |
646 | if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && | |
647 | (pMgmt->eCurrState == WMAC_STATE_ASSOC) && | |
648 | (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) { | |
649 | ev.flags |= IW_MICFAILURE_PAIRWISE; | |
650 | } else { | |
651 | ev.flags |= IW_MICFAILURE_GROUP; | |
652 | } | |
653 | ||
654 | ev.src_addr.sa_family = ARPHRD_ETHER; | |
1cac4a4b | 655 | memcpy(ev.src_addr.sa_data, pMACHeader->addr2, ETH_ALEN); |
92b96797 FB |
656 | memset(&wrqu, 0, sizeof(wrqu)); |
657 | wrqu.data.length = sizeof(ev); | |
658 | PRINT_K("wireless_send_event--->IWEVMICHAELMICFAILURE\n"); | |
659 | wireless_send_event(pDevice->dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); | |
660 | ||
661 | } | |
92b96797 | 662 | |
e269fc2d | 663 | return false; |
92b96797 FB |
664 | |
665 | } | |
666 | } | |
667 | } //---end of SOFT MIC----------------------------------------------------------------------- | |
668 | ||
669 | // ++++++++++ Reply Counter Check +++++++++++++ | |
670 | ||
671 | if ((pKey != NULL) && ((pKey->byCipherSuite == KEY_CTL_TKIP) || | |
672 | (pKey->byCipherSuite == KEY_CTL_CCMP))) { | |
673 | if (bIsWEP) { | |
3eaca0d2 | 674 | u16 wLocalTSC15_0 = 0; |
52a7e64b | 675 | u32 dwLocalTSC47_16 = 0; |
cc856e61 | 676 | unsigned long long RSC = 0; |
92b96797 | 677 | // endian issues |
cc856e61 | 678 | RSC = *((unsigned long long *) &(pKey->KeyRSC)); |
3eaca0d2 | 679 | wLocalTSC15_0 = (u16) RSC; |
52a7e64b | 680 | dwLocalTSC47_16 = (u32) (RSC>>16); |
92b96797 FB |
681 | |
682 | RSC = dwRxTSC47_16; | |
683 | RSC <<= 16; | |
684 | RSC += wRxTSC15_0; | |
7c65fa2a | 685 | memcpy(&(pKey->KeyRSC), &RSC, sizeof(u64)); |
92b96797 | 686 | |
14c5ef57 MP |
687 | if (pDevice->vnt_mgmt.eCurrMode == WMAC_MODE_ESS_STA && |
688 | pDevice->vnt_mgmt.eCurrState == WMAC_STATE_ASSOC) { | |
689 | /* check RSC */ | |
92b96797 FB |
690 | if ( (wRxTSC15_0 < wLocalTSC15_0) && |
691 | (dwRxTSC47_16 <= dwLocalTSC47_16) && | |
692 | !((dwRxTSC47_16 == 0) && (dwLocalTSC47_16 == 0xFFFFFFFF))) { | |
693 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC is illegal~~!\n "); | |
92b96797 FB |
694 | |
695 | if (bDeFragRx) { | |
696 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
697 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
698 | pDevice->dev->name); | |
699 | } | |
700 | } | |
e269fc2d | 701 | return false; |
92b96797 FB |
702 | } |
703 | } | |
704 | } | |
705 | } // ----- End of Reply Counter Check -------------------------- | |
706 | ||
b902fbfe | 707 | s_vProcessRxMACHeader(pDevice, (u8 *)(skb->data+8), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset); |
92b96797 FB |
708 | FrameSize -= cbHeaderOffset; |
709 | cbHeaderOffset += 8; // 8 is Rcv buffer header | |
710 | ||
711 | // Null data, framesize = 12 | |
712 | if (FrameSize < 12) | |
e269fc2d | 713 | return false; |
92b96797 | 714 | |
92b96797 FB |
715 | skb->data += cbHeaderOffset; |
716 | skb->tail += cbHeaderOffset; | |
717 | skb_put(skb, FrameSize); | |
718 | skb->protocol=eth_type_trans(skb, skb->dev); | |
719 | skb->ip_summed=CHECKSUM_NONE; | |
720 | pStats->rx_bytes +=skb->len; | |
721 | pStats->rx_packets++; | |
722 | netif_rx(skb); | |
723 | if (bDeFragRx) { | |
724 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
725 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
726 | pDevice->dev->name); | |
727 | } | |
e269fc2d | 728 | return false; |
92b96797 FB |
729 | } |
730 | ||
4e9b5e2b | 731 | return true; |
92b96797 FB |
732 | } |
733 | ||
45c73bb1 MP |
734 | static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame, |
735 | u32 FrameSize, u8 *pbyRsr, u8 *pbyNewRsr, PSKeyItem *pKeyOut, | |
736 | s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16) | |
92b96797 | 737 | { |
45c73bb1 MP |
738 | struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; |
739 | u32 PayloadLen = FrameSize; | |
740 | u8 *pbyIV; | |
741 | u8 byKeyIdx; | |
742 | PSKeyItem pKey = NULL; | |
743 | u8 byDecMode = KEY_CTL_WEP; | |
92b96797 | 744 | |
92b96797 FB |
745 | *pwRxTSC15_0 = 0; |
746 | *pdwRxTSC47_16 = 0; | |
747 | ||
748 | pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; | |
3eaca0d2 AM |
749 | if ( WLAN_GET_FC_TODS(*(u16 *)pbyFrame) && |
750 | WLAN_GET_FC_FROMDS(*(u16 *)pbyFrame) ) { | |
92b96797 FB |
751 | pbyIV += 6; // 6 is 802.11 address4 |
752 | PayloadLen -= 6; | |
753 | } | |
754 | byKeyIdx = (*(pbyIV+3) & 0xc0); | |
755 | byKeyIdx >>= 6; | |
756 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx); | |
757 | ||
758 | if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || | |
759 | (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || | |
760 | (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || | |
761 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || | |
762 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { | |
763 | if (((*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) && | |
764 | (pMgmt->byCSSPK != KEY_CTL_NONE)) { | |
765 | // unicast pkt use pairwise key | |
766 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt\n"); | |
4e9b5e2b | 767 | if (KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, 0xFFFFFFFF, &pKey) == true) { |
92b96797 FB |
768 | if (pMgmt->byCSSPK == KEY_CTL_TKIP) |
769 | byDecMode = KEY_CTL_TKIP; | |
770 | else if (pMgmt->byCSSPK == KEY_CTL_CCMP) | |
771 | byDecMode = KEY_CTL_CCMP; | |
772 | } | |
773 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt: %d, %p\n", byDecMode, pKey); | |
774 | } else { | |
775 | // use group key | |
776 | KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, byKeyIdx, &pKey); | |
777 | if (pMgmt->byCSSGK == KEY_CTL_TKIP) | |
778 | byDecMode = KEY_CTL_TKIP; | |
779 | else if (pMgmt->byCSSGK == KEY_CTL_CCMP) | |
780 | byDecMode = KEY_CTL_CCMP; | |
781 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"group pkt: %d, %d, %p\n", byKeyIdx, byDecMode, pKey); | |
782 | } | |
783 | } | |
784 | // our WEP only support Default Key | |
785 | if (pKey == NULL) { | |
786 | // use default group key | |
787 | KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, byKeyIdx, &pKey); | |
788 | if (pMgmt->byCSSGK == KEY_CTL_TKIP) | |
789 | byDecMode = KEY_CTL_TKIP; | |
790 | else if (pMgmt->byCSSGK == KEY_CTL_CCMP) | |
791 | byDecMode = KEY_CTL_CCMP; | |
792 | } | |
793 | *pKeyOut = pKey; | |
794 | ||
795 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pMgmt->byCSSPK, pMgmt->byCSSGK, byDecMode); | |
796 | ||
797 | if (pKey == NULL) { | |
798 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey == NULL\n"); | |
e269fc2d | 799 | return false; |
92b96797 FB |
800 | } |
801 | if (byDecMode != pKey->byCipherSuite) { | |
92b96797 | 802 | *pKeyOut = NULL; |
e269fc2d | 803 | return false; |
92b96797 FB |
804 | } |
805 | if (byDecMode == KEY_CTL_WEP) { | |
806 | // handle WEP | |
807 | if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || | |
4e9b5e2b | 808 | (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true)) { |
92b96797 FB |
809 | // Software WEP |
810 | // 1. 3253A | |
811 | // 2. WEP 256 | |
812 | ||
813 | PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc | |
3e362598 JL |
814 | memcpy(pDevice->abyPRNG, pbyIV, 3); |
815 | memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength); | |
92b96797 FB |
816 | rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3); |
817 | rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen); | |
818 | ||
819 | if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) { | |
820 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
821 | } | |
822 | } | |
823 | } else if ((byDecMode == KEY_CTL_TKIP) || | |
824 | (byDecMode == KEY_CTL_CCMP)) { | |
825 | // TKIP/AES | |
826 | ||
827 | PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc | |
52a7e64b | 828 | *pdwRxTSC47_16 = cpu_to_le32(*(u32 *)(pbyIV + 4)); |
b4dc03af | 829 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); |
92b96797 FB |
830 | if (byDecMode == KEY_CTL_TKIP) { |
831 | *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); | |
832 | } else { | |
3eaca0d2 | 833 | *pwRxTSC15_0 = cpu_to_le16(*(u16 *)pbyIV); |
92b96797 FB |
834 | } |
835 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); | |
836 | ||
837 | if ((byDecMode == KEY_CTL_TKIP) && | |
838 | (pDevice->byLocalID <= REV_ID_VT3253_A1)) { | |
839 | // Software TKIP | |
840 | // 1. 3253 A | |
1cac4a4b AM |
841 | struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *) (pbyFrame); |
842 | TKIPvMixKey(pKey->abyKey, pMACHeader->addr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG); | |
92b96797 FB |
843 | rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); |
844 | rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen); | |
845 | if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) { | |
846 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
847 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n"); | |
848 | } else { | |
849 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n"); | |
850 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen); | |
851 | } | |
852 | } | |
853 | }// end of TKIP/AES | |
854 | ||
855 | if ((*(pbyIV+3) & 0x20) != 0) | |
4e9b5e2b AM |
856 | *pbExtIV = true; |
857 | return true; | |
92b96797 FB |
858 | } |
859 | ||
81d720d3 | 860 | void RXvWorkItem(struct work_struct *work) |
92b96797 | 861 | { |
49d73a98 | 862 | struct vnt_private *priv = |
81d720d3 | 863 | container_of(work, struct vnt_private, read_work_item); |
49d73a98 MP |
864 | int status; |
865 | struct vnt_rcb *rcb = NULL; | |
0b596b2a | 866 | unsigned long flags; |
92b96797 | 867 | |
49d73a98 | 868 | if (priv->Flags & fMP_DISCONNECTED) |
17f3ced0 MP |
869 | return; |
870 | ||
49d73a98 | 871 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n"); |
731047f9 | 872 | |
0b596b2a | 873 | spin_lock_irqsave(&priv->lock, flags); |
49d73a98 MP |
874 | |
875 | while ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) && | |
876 | (priv->NumRecvFreeList != 0)) { | |
877 | rcb = priv->FirstRecvFreeList; | |
878 | ||
879 | priv->NumRecvFreeList--; | |
880 | ||
881 | DequeueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList); | |
882 | ||
883 | status = PIPEnsBulkInUsbRead(priv, rcb); | |
884 | } | |
885 | ||
886 | priv->bIsRxWorkItemQueued = false; | |
92b96797 | 887 | |
0b596b2a | 888 | spin_unlock_irqrestore(&priv->lock, flags); |
92b96797 FB |
889 | } |
890 | ||
5a30e0b6 | 891 | void RXvFreeRCB(struct vnt_rcb *rcb, int re_alloc_skb) |
92b96797 | 892 | { |
5a30e0b6 | 893 | struct vnt_private *priv = rcb->pDevice; |
92b96797 | 894 | |
5a30e0b6 | 895 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n"); |
92b96797 | 896 | |
5a30e0b6 MP |
897 | if (re_alloc_skb == false) { |
898 | kfree_skb(rcb->skb); | |
899 | re_alloc_skb = true; | |
28044e01 MP |
900 | } |
901 | ||
5a30e0b6 | 902 | if (re_alloc_skb == true) { |
29263661 | 903 | rcb->skb = netdev_alloc_skb(priv->dev, priv->rx_buf_sz); |
5a30e0b6 | 904 | /* TODO error handling */ |
29263661 | 905 | if (!rcb->skb) { |
5a30e0b6 MP |
906 | DBG_PRT(MSG_LEVEL_ERR, KERN_ERR |
907 | " Failed to re-alloc rx skb\n"); | |
5a30e0b6 MP |
908 | } |
909 | } | |
92b96797 | 910 | |
5a30e0b6 MP |
911 | /* Insert the RCB back in the Recv free list */ |
912 | EnqueueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList, rcb); | |
913 | priv->NumRecvFreeList++; | |
92b96797 | 914 | |
5a30e0b6 MP |
915 | if ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) && |
916 | (priv->bIsRxWorkItemQueued == false)) { | |
917 | priv->bIsRxWorkItemQueued = true; | |
918 | schedule_work(&priv->read_work_item); | |
919 | } | |
920 | ||
921 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n", | |
922 | priv->NumRecvFreeList, priv->NumRecvMngList); | |
92b96797 FB |
923 | } |
924 | ||
a21fc2f5 | 925 | void RXvMngWorkItem(struct work_struct *work) |
92b96797 | 926 | { |
a21fc2f5 MP |
927 | struct vnt_private *pDevice = |
928 | container_of(work, struct vnt_private, rx_mng_work_item); | |
115cac2e | 929 | struct vnt_rcb *pRCB = NULL; |
45c73bb1 | 930 | struct vnt_rx_mgmt *pRxPacket; |
e269fc2d | 931 | int bReAllocSkb = false; |
e03ce839 | 932 | unsigned long flags; |
92b96797 | 933 | |
17f3ced0 MP |
934 | if (pDevice->Flags & fMP_DISCONNECTED) |
935 | return; | |
936 | ||
92b96797 FB |
937 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Mng Thread\n"); |
938 | ||
92b96797 FB |
939 | while (pDevice->NumRecvMngList!=0) |
940 | { | |
e03ce839 MP |
941 | spin_lock_irqsave(&pDevice->lock, flags); |
942 | ||
92b96797 FB |
943 | pRCB = pDevice->FirstRecvMngList; |
944 | pDevice->NumRecvMngList--; | |
945 | DequeueRCB(pDevice->FirstRecvMngList, pDevice->LastRecvMngList); | |
e03ce839 MP |
946 | |
947 | spin_unlock_irqrestore(&pDevice->lock, flags); | |
948 | ||
92b96797 FB |
949 | if(!pRCB){ |
950 | break; | |
951 | } | |
92b96797 | 952 | pRxPacket = &(pRCB->sMngPacket); |
14c5ef57 | 953 | vMgrRxManagePacket(pDevice, &pDevice->vnt_mgmt, pRxPacket); |
92b96797 | 954 | pRCB->Ref--; |
e03ce839 MP |
955 | if (pRCB->Ref == 0) { |
956 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeMng %d %d\n", | |
957 | pDevice->NumRecvFreeList, pDevice->NumRecvMngList); | |
958 | ||
959 | spin_lock_irqsave(&pDevice->lock, flags); | |
960 | ||
961 | RXvFreeRCB(pRCB, bReAllocSkb); | |
962 | ||
963 | spin_unlock_irqrestore(&pDevice->lock, flags); | |
964 | } else { | |
92b96797 FB |
965 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rx Mng Only we have the right to free RCB\n"); |
966 | } | |
967 | } | |
968 | ||
e269fc2d | 969 | pDevice->bIsRxMngWorkItemQueued = false; |
92b96797 FB |
970 | } |
971 |