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 | * | |
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 | |
29 | * s_bAPModeRxCtl- AP Rcv frame filer Ctl. | |
30 | * s_bAPModeRxData- AP Rcv data frame handle | |
31 | * s_bHandleRxEncryption- Rcv decrypted data via on-fly | |
32 | * s_bHostWepRxEncryption- Rcv encrypted data via host | |
33 | * s_byGetRateIdx- get rate index | |
34 | * s_vGetDASA- get data offset | |
35 | * s_vProcessRxMACHeader- Rcv 802.11 and translate to 802.3 | |
36 | * | |
37 | * Revision History: | |
38 | * | |
39 | */ | |
40 | ||
5449c685 | 41 | #include "device.h" |
5449c685 | 42 | #include "rxtx.h" |
5449c685 | 43 | #include "tether.h" |
5449c685 | 44 | #include "card.h" |
5449c685 | 45 | #include "bssdb.h" |
5449c685 | 46 | #include "mac.h" |
5449c685 | 47 | #include "baseband.h" |
5449c685 | 48 | #include "michael.h" |
5449c685 | 49 | #include "tkip.h" |
5449c685 | 50 | #include "tcrc.h" |
5449c685 | 51 | #include "wctl.h" |
5449c685 | 52 | #include "wroute.h" |
5449c685 | 53 | #include "hostap.h" |
5449c685 | 54 | #include "rf.h" |
5449c685 | 55 | #include "iowpa.h" |
5449c685 | 56 | #include "aes_ccmp.h" |
5449c685 FB |
57 | |
58 | //#define PLICE_DEBUG | |
59 | ||
60 | ||
61 | /*--------------------- Static Definitions -------------------------*/ | |
62 | ||
63 | /*--------------------- Static Classes ----------------------------*/ | |
64 | ||
65 | /*--------------------- Static Variables --------------------------*/ | |
66 | //static int msglevel =MSG_LEVEL_DEBUG; | |
67 | static int msglevel =MSG_LEVEL_INFO; | |
68 | ||
3fc9b584 | 69 | const unsigned char acbyRxRate[MAX_RATE] = |
5449c685 FB |
70 | {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; |
71 | ||
72 | ||
73 | /*--------------------- Static Functions --------------------------*/ | |
74 | ||
75 | /*--------------------- Static Definitions -------------------------*/ | |
76 | ||
77 | /*--------------------- Static Functions --------------------------*/ | |
78 | ||
3fc9b584 | 79 | static unsigned char s_byGetRateIdx(unsigned char byRate); |
5449c685 FB |
80 | |
81 | ||
fe4f34bd CC |
82 | static void |
83 | s_vGetDASA(unsigned char *pbyRxBufferAddr, unsigned int *pcbHeaderSize, | |
84 | PSEthernetHeader psEthHeader); | |
5449c685 | 85 | |
fe4f34bd CC |
86 | static void |
87 | s_vProcessRxMACHeader(PSDevice pDevice, unsigned char *pbyRxBufferAddr, | |
7b6a0013 | 88 | unsigned int cbPacketSize, bool bIsWEP, bool bExtIV, |
fe4f34bd | 89 | unsigned int *pcbHeadSize); |
5449c685 | 90 | |
7b6a0013 | 91 | static bool s_bAPModeRxCtl( |
3a215e0f | 92 | PSDevice pDevice, |
2989e96f | 93 | unsigned char *pbyFrame, |
7ca30195 | 94 | int iSANodeIndex |
5449c685 FB |
95 | ); |
96 | ||
5449c685 | 97 | |
612822f5 | 98 | |
7b6a0013 | 99 | static bool s_bAPModeRxData ( |
3a215e0f CC |
100 | PSDevice pDevice, |
101 | struct sk_buff* skb, | |
b6e95cd5 CC |
102 | unsigned int FrameSize, |
103 | unsigned int cbHeaderOffset, | |
7ca30195 CC |
104 | int iSANodeIndex, |
105 | int iDANodeIndex | |
5449c685 | 106 | ); |
5449c685 FB |
107 | |
108 | ||
7b6a0013 | 109 | static bool s_bHandleRxEncryption( |
3a215e0f | 110 | PSDevice pDevice, |
2989e96f | 111 | unsigned char *pbyFrame, |
b6e95cd5 | 112 | unsigned int FrameSize, |
2989e96f CC |
113 | unsigned char *pbyRsr, |
114 | unsigned char *pbyNewRsr, | |
3cdec554 | 115 | PSKeyItem *pKeyOut, |
7b6a0013 | 116 | bool *pbExtIV, |
15df6c2b | 117 | unsigned short *pwRxTSC15_0, |
9d828c45 | 118 | unsigned long *pdwRxTSC47_16 |
5449c685 FB |
119 | ); |
120 | ||
7b6a0013 | 121 | static bool s_bHostWepRxEncryption( |
5449c685 | 122 | |
3a215e0f | 123 | PSDevice pDevice, |
2989e96f | 124 | unsigned char *pbyFrame, |
b6e95cd5 | 125 | unsigned int FrameSize, |
2989e96f | 126 | unsigned char *pbyRsr, |
7b6a0013 | 127 | bool bOnFly, |
3a215e0f | 128 | PSKeyItem pKey, |
2989e96f | 129 | unsigned char *pbyNewRsr, |
7b6a0013 | 130 | bool *pbExtIV, |
15df6c2b | 131 | unsigned short *pwRxTSC15_0, |
9d828c45 | 132 | unsigned long *pdwRxTSC47_16 |
5449c685 FB |
133 | |
134 | ); | |
135 | ||
136 | /*--------------------- Export Variables --------------------------*/ | |
137 | ||
138 | /*+ | |
139 | * | |
140 | * Description: | |
141 | * Translate Rcv 802.11 header to 802.3 header with Rx buffer | |
142 | * | |
143 | * Parameters: | |
144 | * In: | |
145 | * pDevice | |
146 | * dwRxBufferAddr - Address of Rcv Buffer | |
147 | * cbPacketSize - Rcv Packet size | |
148 | * bIsWEP - If Rcv with WEP | |
149 | * Out: | |
150 | * pcbHeaderSize - 802.11 header size | |
151 | * | |
152 | * Return Value: None | |
153 | * | |
154 | -*/ | |
fe4f34bd CC |
155 | static void |
156 | s_vProcessRxMACHeader(PSDevice pDevice, unsigned char *pbyRxBufferAddr, | |
7b6a0013 | 157 | unsigned int cbPacketSize, bool bIsWEP, bool bExtIV, |
fe4f34bd | 158 | unsigned int *pcbHeadSize) |
5449c685 | 159 | { |
2989e96f | 160 | unsigned char *pbyRxBuffer; |
b6e95cd5 | 161 | unsigned int cbHeaderSize = 0; |
15df6c2b | 162 | unsigned short *pwType; |
5449c685 FB |
163 | PS802_11Header pMACHeader; |
164 | int ii; | |
165 | ||
166 | ||
167 | pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize); | |
168 | ||
2989e96f | 169 | s_vGetDASA((unsigned char *)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader); |
5449c685 FB |
170 | |
171 | if (bIsWEP) { | |
172 | if (bExtIV) { | |
173 | // strip IV&ExtIV , add 8 byte | |
174 | cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 8); | |
175 | } else { | |
176 | // strip IV , add 4 byte | |
177 | cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 4); | |
178 | } | |
179 | } | |
180 | else { | |
181 | cbHeaderSize += WLAN_HDR_ADDR3_LEN; | |
182 | }; | |
183 | ||
2989e96f | 184 | pbyRxBuffer = (unsigned char *) (pbyRxBufferAddr + cbHeaderSize); |
2ef98c60 | 185 | if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) { |
5449c685 FB |
186 | cbHeaderSize += 6; |
187 | } | |
2ef98c60 | 188 | else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { |
5449c685 | 189 | cbHeaderSize += 6; |
15df6c2b | 190 | pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize); |
5449c685 FB |
191 | if ((*pwType!= TYPE_PKT_IPX) && (*pwType != cpu_to_le16(0xF380))) { |
192 | } | |
193 | else { | |
194 | cbHeaderSize -= 8; | |
15df6c2b | 195 | pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize); |
5449c685 FB |
196 | if (bIsWEP) { |
197 | if (bExtIV) { | |
198 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV | |
199 | } else { | |
200 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV | |
201 | } | |
202 | } | |
203 | else { | |
204 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); | |
205 | } | |
206 | } | |
207 | } | |
208 | else { | |
209 | cbHeaderSize -= 2; | |
15df6c2b | 210 | pwType = (unsigned short *) (pbyRxBufferAddr + cbHeaderSize); |
5449c685 FB |
211 | if (bIsWEP) { |
212 | if (bExtIV) { | |
213 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV | |
214 | } else { | |
215 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV | |
216 | } | |
217 | } | |
218 | else { | |
219 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); | |
220 | } | |
221 | } | |
222 | ||
078b078f | 223 | cbHeaderSize -= (ETH_ALEN * 2); |
2989e96f | 224 | pbyRxBuffer = (unsigned char *) (pbyRxBufferAddr + cbHeaderSize); |
078b078f | 225 | for(ii=0;ii<ETH_ALEN;ii++) |
5449c685 | 226 | *pbyRxBuffer++ = pDevice->sRxEthHeader.abyDstAddr[ii]; |
078b078f | 227 | for(ii=0;ii<ETH_ALEN;ii++) |
5449c685 FB |
228 | *pbyRxBuffer++ = pDevice->sRxEthHeader.abySrcAddr[ii]; |
229 | ||
230 | *pcbHeadSize = cbHeaderSize; | |
231 | } | |
232 | ||
233 | ||
234 | ||
235 | ||
3fc9b584 | 236 | static unsigned char s_byGetRateIdx (unsigned char byRate) |
5449c685 | 237 | { |
3fc9b584 | 238 | unsigned char byRateIdx; |
5449c685 FB |
239 | |
240 | for (byRateIdx = 0; byRateIdx <MAX_RATE ; byRateIdx++) { | |
241 | if (acbyRxRate[byRateIdx%MAX_RATE] == byRate) | |
242 | return byRateIdx; | |
243 | } | |
244 | return 0; | |
245 | } | |
246 | ||
247 | ||
fe4f34bd CC |
248 | static void |
249 | s_vGetDASA(unsigned char *pbyRxBufferAddr, unsigned int *pcbHeaderSize, | |
250 | PSEthernetHeader psEthHeader) | |
5449c685 | 251 | { |
b6e95cd5 | 252 | unsigned int cbHeaderSize = 0; |
5449c685 FB |
253 | PS802_11Header pMACHeader; |
254 | int ii; | |
255 | ||
256 | pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize); | |
257 | ||
258 | if ((pMACHeader->wFrameCtl & FC_TODS) == 0) { | |
259 | if (pMACHeader->wFrameCtl & FC_FROMDS) { | |
078b078f | 260 | for(ii=0;ii<ETH_ALEN;ii++) { |
5449c685 FB |
261 | psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr1[ii]; |
262 | psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr3[ii]; | |
263 | } | |
264 | } | |
265 | else { | |
266 | // IBSS mode | |
078b078f | 267 | for(ii=0;ii<ETH_ALEN;ii++) { |
5449c685 FB |
268 | psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr1[ii]; |
269 | psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii]; | |
270 | } | |
271 | } | |
272 | } | |
273 | else { | |
274 | // Is AP mode.. | |
275 | if (pMACHeader->wFrameCtl & FC_FROMDS) { | |
078b078f | 276 | for(ii=0;ii<ETH_ALEN;ii++) { |
5449c685 FB |
277 | psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr3[ii]; |
278 | psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr4[ii]; | |
279 | cbHeaderSize += 6; | |
280 | } | |
281 | } | |
282 | else { | |
078b078f | 283 | for(ii=0;ii<ETH_ALEN;ii++) { |
5449c685 FB |
284 | psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr3[ii]; |
285 | psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii]; | |
286 | } | |
287 | } | |
288 | }; | |
289 | *pcbHeaderSize = cbHeaderSize; | |
290 | } | |
291 | ||
292 | ||
293 | ||
294 | ||
295 | //PLICE_DEBUG -> | |
296 | ||
830a619c | 297 | void MngWorkItem(void *Context) |
5449c685 FB |
298 | { |
299 | PSRxMgmtPacket pRxMgmtPacket; | |
300 | PSDevice pDevice = (PSDevice) Context; | |
301 | //printk("Enter MngWorkItem,Queue packet num is %d\n",pDevice->rxManeQueue.packet_num); | |
302 | spin_lock_irq(&pDevice->lock); | |
303 | while(pDevice->rxManeQueue.packet_num != 0) | |
304 | { | |
305 | pRxMgmtPacket = DeQueue(pDevice); | |
306 | vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket); | |
307 | } | |
308 | spin_unlock_irq(&pDevice->lock); | |
309 | } | |
310 | ||
311 | ||
312 | //PLICE_DEBUG<- | |
313 | ||
314 | ||
315 | ||
7b6a0013 | 316 | bool |
5449c685 | 317 | device_receive_frame ( |
3a215e0f CC |
318 | PSDevice pDevice, |
319 | PSRxDesc pCurrRD | |
5449c685 FB |
320 | ) |
321 | { | |
322 | ||
323 | PDEVICE_RD_INFO pRDInfo = pCurrRD->pRDInfo; | |
324 | #ifdef PLICE_DEBUG | |
325 | //printk("device_receive_frame:pCurrRD is %x,pRDInfo is %x\n",pCurrRD,pCurrRD->pRDInfo); | |
326 | #endif | |
327 | struct net_device_stats* pStats=&pDevice->stats; | |
5449c685 | 328 | struct sk_buff* skb; |
5449c685 FB |
329 | PSMgmtObject pMgmt = pDevice->pMgmt; |
330 | PSRxMgmtPacket pRxPacket = &(pDevice->pMgmt->sRxPacket); | |
331 | PS802_11Header p802_11Header; | |
2989e96f CC |
332 | unsigned char *pbyRsr; |
333 | unsigned char *pbyNewRsr; | |
334 | unsigned char *pbyRSSI; | |
5449c685 | 335 | PQWORD pqwTSFTime; |
15df6c2b | 336 | unsigned short *pwFrameSize; |
2989e96f | 337 | unsigned char *pbyFrame; |
7b6a0013 CC |
338 | bool bDeFragRx = false; |
339 | bool bIsWEP = false; | |
b6e95cd5 CC |
340 | unsigned int cbHeaderOffset; |
341 | unsigned int FrameSize; | |
2986db5f | 342 | unsigned short wEtherType = 0; |
7ca30195 CC |
343 | int iSANodeIndex = -1; |
344 | int iDANodeIndex = -1; | |
b6e95cd5 CC |
345 | unsigned int ii; |
346 | unsigned int cbIVOffset; | |
7b6a0013 | 347 | bool bExtIV = false; |
2989e96f CC |
348 | unsigned char *pbyRxSts; |
349 | unsigned char *pbyRxRate; | |
350 | unsigned char *pbySQ; | |
b6e95cd5 | 351 | unsigned int cbHeaderSize; |
5449c685 | 352 | PSKeyItem pKey = NULL; |
2986db5f | 353 | unsigned short wRxTSC15_0 = 0; |
0f4c60d6 | 354 | unsigned long dwRxTSC47_16 = 0; |
5449c685 FB |
355 | SKeyItem STempKey; |
356 | // 802.11h RPI | |
0f4c60d6 | 357 | unsigned long dwDuration = 0; |
b83cc2ed CC |
358 | long ldBm = 0; |
359 | long ldBmThreshold = 0; | |
5449c685 | 360 | PS802_11Header pMACHeader; |
7b6a0013 | 361 | bool bRxeapol_key = false; |
5449c685 | 362 | |
7e809a9b | 363 | // DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- device_receive_frame---\n"); |
5449c685 FB |
364 | |
365 | skb = pRDInfo->skb; | |
5449c685 FB |
366 | |
367 | ||
368 | //PLICE_DEBUG-> | |
369 | #if 1 | |
370 | pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma, | |
371 | pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); | |
372 | #endif | |
373 | //PLICE_DEBUG<- | |
15df6c2b | 374 | pwFrameSize = (unsigned short *)(skb->data + 2); |
5449c685 FB |
375 | FrameSize = cpu_to_le16(pCurrRD->m_rd1RD1.wReqCount) - cpu_to_le16(pCurrRD->m_rd0RD0.wResCount); |
376 | ||
377 | // Max: 2312Payload + 30HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR | |
378 | // Min (ACK): 10HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR | |
379 | if ((FrameSize > 2364)||(FrameSize <= 32)) { | |
380 | // Frame Size error drop this packet. | |
7e809a9b | 381 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- WRONG Length 1 \n"); |
5a5a2a6a | 382 | return false; |
5449c685 FB |
383 | } |
384 | ||
2989e96f CC |
385 | pbyRxSts = (unsigned char *) (skb->data); |
386 | pbyRxRate = (unsigned char *) (skb->data + 1); | |
387 | pbyRsr = (unsigned char *) (skb->data + FrameSize - 1); | |
388 | pbyRSSI = (unsigned char *) (skb->data + FrameSize - 2); | |
389 | pbyNewRsr = (unsigned char *) (skb->data + FrameSize - 3); | |
390 | pbySQ = (unsigned char *) (skb->data + FrameSize - 4); | |
5449c685 | 391 | pqwTSFTime = (PQWORD) (skb->data + FrameSize - 12); |
2989e96f | 392 | pbyFrame = (unsigned char *)(skb->data + 4); |
5449c685 FB |
393 | |
394 | // get packet size | |
395 | FrameSize = cpu_to_le16(*pwFrameSize); | |
396 | ||
397 | if ((FrameSize > 2346)|(FrameSize < 14)) { // Max: 2312Payload + 30HD +4CRC | |
398 | // Min: 14 bytes ACK | |
7e809a9b | 399 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- WRONG Length 2 \n"); |
5a5a2a6a | 400 | return false; |
5449c685 FB |
401 | } |
402 | //PLICE_DEBUG-> | |
403 | #if 1 | |
404 | // update receive statistic counter | |
405 | STAvUpdateRDStatCounter(&pDevice->scStatistic, | |
406 | *pbyRsr, | |
407 | *pbyNewRsr, | |
408 | *pbyRxRate, | |
409 | pbyFrame, | |
410 | FrameSize); | |
411 | ||
412 | #endif | |
413 | ||
2989e96f | 414 | pMACHeader=(PS802_11Header)((unsigned char *) (skb->data)+8); |
5449c685 | 415 | //PLICE_DEBUG<- |
1b12068a | 416 | if (pDevice->bMeasureInProgress == true) { |
5449c685 FB |
417 | if ((*pbyRsr & RSR_CRCOK) != 0) { |
418 | pDevice->byBasicMap |= 0x01; | |
419 | } | |
420 | dwDuration = (FrameSize << 4); | |
421 | dwDuration /= acbyRxRate[*pbyRxRate%MAX_RATE]; | |
422 | if (*pbyRxRate <= RATE_11M) { | |
256a816b | 423 | if (*pbyRxSts & 0x01) { |
5449c685 FB |
424 | // long preamble |
425 | dwDuration += 192; | |
426 | } else { | |
427 | // short preamble | |
428 | dwDuration += 96; | |
429 | } | |
430 | } else { | |
431 | dwDuration += 16; | |
432 | } | |
433 | RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); | |
434 | ldBmThreshold = -57; | |
435 | for (ii = 7; ii > 0;) { | |
436 | if (ldBm > ldBmThreshold) { | |
437 | break; | |
438 | } | |
439 | ldBmThreshold -= 5; | |
440 | ii--; | |
441 | } | |
442 | pDevice->dwRPIs[ii] += dwDuration; | |
5a5a2a6a | 443 | return false; |
5449c685 FB |
444 | } |
445 | ||
388bf2e8 | 446 | if (!is_multicast_ether_addr(pbyFrame)) { |
5449c685 FB |
447 | if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header) (skb->data + 4))) { |
448 | pDevice->s802_11Counter.FrameDuplicateCount++; | |
5a5a2a6a | 449 | return false; |
5449c685 FB |
450 | } |
451 | } | |
452 | ||
453 | ||
454 | // Use for TKIP MIC | |
455 | s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader); | |
456 | ||
457 | // filter packet send from myself | |
2989e96f | 458 | if (!compare_ether_addr((unsigned char *)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr)) |
5a5a2a6a | 459 | return false; |
5449c685 FB |
460 | |
461 | if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { | |
462 | if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { | |
463 | p802_11Header = (PS802_11Header) (pbyFrame); | |
464 | // get SA NodeIndex | |
2989e96f | 465 | if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(p802_11Header->abyAddr2), &iSANodeIndex)) { |
5449c685 | 466 | pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies; |
5449c685 FB |
467 | pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0; |
468 | } | |
469 | } | |
470 | } | |
471 | ||
472 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { | |
1b12068a | 473 | if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex) == true) { |
5a5a2a6a | 474 | return false; |
5449c685 FB |
475 | } |
476 | } | |
612822f5 JL |
477 | |
478 | ||
5449c685 | 479 | if (IS_FC_WEP(pbyFrame)) { |
7b6a0013 | 480 | bool bRxDecryOK = false; |
5449c685 | 481 | |
7e809a9b | 482 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rx WEP pkt\n"); |
1b12068a | 483 | bIsWEP = true; |
5449c685 FB |
484 | if ((pDevice->bEnableHostWEP) && (iSANodeIndex >= 0)) { |
485 | pKey = &STempKey; | |
486 | pKey->byCipherSuite = pMgmt->sNodeDBTable[iSANodeIndex].byCipherSuite; | |
487 | pKey->dwKeyIndex = pMgmt->sNodeDBTable[iSANodeIndex].dwKeyIndex; | |
488 | pKey->uKeyLength = pMgmt->sNodeDBTable[iSANodeIndex].uWepKeyLength; | |
489 | pKey->dwTSC47_16 = pMgmt->sNodeDBTable[iSANodeIndex].dwTSC47_16; | |
490 | pKey->wTSC15_0 = pMgmt->sNodeDBTable[iSANodeIndex].wTSC15_0; | |
491 | memcpy(pKey->abyKey, | |
492 | &pMgmt->sNodeDBTable[iSANodeIndex].abyWepKey[0], | |
493 | pKey->uKeyLength | |
494 | ); | |
495 | ||
496 | bRxDecryOK = s_bHostWepRxEncryption(pDevice, | |
497 | pbyFrame, | |
498 | FrameSize, | |
499 | pbyRsr, | |
500 | pMgmt->sNodeDBTable[iSANodeIndex].bOnFly, | |
501 | pKey, | |
502 | pbyNewRsr, | |
503 | &bExtIV, | |
504 | &wRxTSC15_0, | |
505 | &dwRxTSC47_16); | |
506 | } else { | |
507 | bRxDecryOK = s_bHandleRxEncryption(pDevice, | |
508 | pbyFrame, | |
509 | FrameSize, | |
510 | pbyRsr, | |
511 | pbyNewRsr, | |
512 | &pKey, | |
513 | &bExtIV, | |
514 | &wRxTSC15_0, | |
515 | &dwRxTSC47_16); | |
516 | } | |
517 | ||
518 | if (bRxDecryOK) { | |
519 | if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) { | |
7e809a9b | 520 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV Fail\n"); |
5449c685 FB |
521 | if ( (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA) || |
522 | (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || | |
523 | (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || | |
524 | (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || | |
525 | (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { | |
526 | ||
527 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { | |
528 | pDevice->s802_11Counter.TKIPICVErrors++; | |
529 | } else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) { | |
530 | pDevice->s802_11Counter.CCMPDecryptErrors++; | |
531 | } else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_WEP)) { | |
532 | // pDevice->s802_11Counter.WEPICVErrorCount.QuadPart++; | |
533 | } | |
534 | } | |
5a5a2a6a | 535 | return false; |
5449c685 FB |
536 | } |
537 | } else { | |
7e809a9b | 538 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WEP Func Fail\n"); |
5a5a2a6a | 539 | return false; |
5449c685 FB |
540 | } |
541 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) | |
542 | FrameSize -= 8; // Message Integrity Code | |
543 | else | |
544 | FrameSize -= 4; // 4 is ICV | |
545 | } | |
546 | ||
547 | ||
548 | // | |
549 | // RX OK | |
550 | // | |
551 | //remove the CRC length | |
855181f5 | 552 | FrameSize -= ETH_FCS_LEN; |
5449c685 | 553 | |
256a816b | 554 | if (( !(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI))) && // unicast address |
5449c685 FB |
555 | (IS_FRAGMENT_PKT((skb->data+4))) |
556 | ) { | |
557 | // defragment | |
558 | bDeFragRx = WCTLbHandleFragment(pDevice, (PS802_11Header) (skb->data+4), FrameSize, bIsWEP, bExtIV); | |
559 | pDevice->s802_11Counter.ReceivedFragmentCount++; | |
560 | if (bDeFragRx) { | |
561 | // defrag complete | |
5449c685 | 562 | skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb; |
5449c685 FB |
563 | FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength; |
564 | ||
565 | } | |
566 | else { | |
5a5a2a6a | 567 | return false; |
5449c685 FB |
568 | } |
569 | } | |
570 | ||
571 | ||
572 | // Management & Control frame Handle | |
5a5a2a6a | 573 | if ((IS_TYPE_DATA((skb->data+4))) == false) { |
5449c685 FB |
574 | // Handle Control & Manage Frame |
575 | ||
576 | if (IS_TYPE_MGMT((skb->data+4))) { | |
2989e96f CC |
577 | unsigned char *pbyData1; |
578 | unsigned char *pbyData2; | |
5449c685 FB |
579 | |
580 | pRxPacket->p80211Header = (PUWLAN_80211HDR)(skb->data+4); | |
581 | pRxPacket->cbMPDULen = FrameSize; | |
582 | pRxPacket->uRSSI = *pbyRSSI; | |
583 | pRxPacket->bySQ = *pbySQ; | |
584 | HIDWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(HIDWORD(*pqwTSFTime)); | |
585 | LODWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(LODWORD(*pqwTSFTime)); | |
586 | if (bIsWEP) { | |
587 | // strip IV | |
588 | pbyData1 = WLAN_HDR_A3_DATA_PTR(skb->data+4); | |
589 | pbyData2 = WLAN_HDR_A3_DATA_PTR(skb->data+4) + 4; | |
590 | for (ii = 0; ii < (FrameSize - 4); ii++) { | |
591 | *pbyData1 = *pbyData2; | |
592 | pbyData1++; | |
593 | pbyData2++; | |
594 | } | |
595 | } | |
596 | pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate); | |
597 | pRxPacket->byRxChannel = (*pbyRxSts) >> 2; | |
598 | //PLICE_DEBUG-> | |
599 | //EnQueue(pDevice,pRxPacket); | |
600 | ||
601 | #ifdef THREAD | |
602 | EnQueue(pDevice,pRxPacket); | |
603 | ||
604 | //printk("enque time is %x\n",jiffies); | |
605 | //up(&pDevice->mlme_semaphore); | |
606 | //Enque (pDevice->FirstRecvMngList,pDevice->LastRecvMngList,pMgmt); | |
607 | #else | |
608 | ||
609 | #ifdef TASK_LET | |
610 | EnQueue(pDevice,pRxPacket); | |
611 | tasklet_schedule(&pDevice->RxMngWorkItem); | |
612 | #else | |
613 | //printk("RxMan\n"); | |
e64354c0 | 614 | vMgrRxManagePacket((void *)pDevice, pDevice->pMgmt, pRxPacket); |
5449c685 FB |
615 | //tasklet_schedule(&pDevice->RxMngWorkItem); |
616 | #endif | |
617 | ||
618 | #endif | |
619 | //PLICE_DEBUG<- | |
e64354c0 | 620 | //vMgrRxManagePacket((void *)pDevice, pDevice->pMgmt, pRxPacket); |
5449c685 FB |
621 | // hostap Deamon handle 802.11 management |
622 | if (pDevice->bEnableHostapd) { | |
623 | skb->dev = pDevice->apdev; | |
5449c685 FB |
624 | skb->data += 4; |
625 | skb->tail += 4; | |
626 | skb_put(skb, FrameSize); | |
db6cb903 | 627 | skb_reset_mac_header(skb); |
5449c685 FB |
628 | skb->pkt_type = PACKET_OTHERHOST; |
629 | skb->protocol = htons(ETH_P_802_2); | |
630 | memset(skb->cb, 0, sizeof(skb->cb)); | |
631 | netif_rx(skb); | |
1b12068a | 632 | return true; |
5449c685 FB |
633 | } |
634 | } | |
635 | else { | |
636 | // Control Frame | |
637 | }; | |
5a5a2a6a | 638 | return false; |
5449c685 FB |
639 | } |
640 | else { | |
641 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { | |
642 | //In AP mode, hw only check addr1(BSSID or RA) if equal to local MAC. | |
256a816b | 643 | if ( !(*pbyRsr & RSR_BSSIDOK)) { |
5449c685 FB |
644 | if (bDeFragRx) { |
645 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
7e809a9b | 646 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", |
5449c685 FB |
647 | pDevice->dev->name); |
648 | } | |
649 | } | |
5a5a2a6a | 650 | return false; |
5449c685 FB |
651 | } |
652 | } | |
653 | else { | |
654 | // discard DATA packet while not associate || BSSID error | |
5a5a2a6a | 655 | if ((pDevice->bLinkPass == false) || |
256a816b | 656 | !(*pbyRsr & RSR_BSSIDOK)) { |
5449c685 FB |
657 | if (bDeFragRx) { |
658 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
7e809a9b | 659 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", |
5449c685 FB |
660 | pDevice->dev->name); |
661 | } | |
662 | } | |
5a5a2a6a | 663 | return false; |
5449c685 | 664 | } |
5449c685 FB |
665 | //mike add:station mode check eapol-key challenge---> |
666 | { | |
3fc9b584 CC |
667 | unsigned char Protocol_Version; //802.1x Authentication |
668 | unsigned char Packet_Type; //802.1x Authentication | |
5449c685 FB |
669 | if (bIsWEP) |
670 | cbIVOffset = 8; | |
671 | else | |
672 | cbIVOffset = 0; | |
673 | wEtherType = (skb->data[cbIVOffset + 8 + 24 + 6] << 8) | | |
674 | skb->data[cbIVOffset + 8 + 24 + 6 + 1]; | |
675 | Protocol_Version = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1]; | |
676 | Packet_Type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1]; | |
677 | if (wEtherType == ETH_P_PAE) { //Protocol Type in LLC-Header | |
678 | if(((Protocol_Version==1) ||(Protocol_Version==2)) && | |
679 | (Packet_Type==3)) { //802.1x OR eapol-key challenge frame receive | |
1b12068a | 680 | bRxeapol_key = true; |
5449c685 FB |
681 | } |
682 | } | |
683 | } | |
684 | //mike add:station mode check eapol-key challenge<--- | |
685 | } | |
686 | } | |
687 | ||
612822f5 | 688 | |
5449c685 FB |
689 | // Data frame Handle |
690 | ||
612822f5 | 691 | |
5449c685 FB |
692 | if (pDevice->bEnablePSMode) { |
693 | if (IS_FC_MOREDATA((skb->data+4))) { | |
256a816b | 694 | if (*pbyRsr & RSR_ADDROK) { |
5449c685 FB |
695 | //PSbSendPSPOLL((PSDevice)pDevice); |
696 | } | |
697 | } | |
698 | else { | |
1b12068a | 699 | if (pDevice->pMgmt->bInTIMWake == true) { |
5a5a2a6a | 700 | pDevice->pMgmt->bInTIMWake = false; |
5449c685 FB |
701 | } |
702 | } | |
9fc86028 | 703 | } |
5449c685 FB |
704 | |
705 | // Now it only supports 802.11g Infrastructure Mode, and support rate must up to 54 Mbps | |
706 | if (pDevice->bDiversityEnable && (FrameSize>50) && | |
707 | (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) && | |
1b12068a | 708 | (pDevice->bLinkPass == true)) { |
5449c685 FB |
709 | //printk("device_receive_frame: RxRate is %d\n",*pbyRxRate); |
710 | BBvAntennaDiversity(pDevice, s_byGetRateIdx(*pbyRxRate), 0); | |
711 | } | |
712 | ||
713 | ||
714 | if (pDevice->byLocalID != REV_ID_VT3253_B1) { | |
715 | pDevice->uCurrRSSI = *pbyRSSI; | |
716 | } | |
717 | pDevice->byCurrSQ = *pbySQ; | |
718 | ||
719 | if ((*pbyRSSI != 0) && | |
720 | (pMgmt->pCurrBSS!=NULL)) { | |
721 | RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); | |
722 | // Moniter if RSSI is too strong. | |
723 | pMgmt->pCurrBSS->byRSSIStatCnt++; | |
724 | pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT; | |
725 | pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm; | |
726 | for(ii=0;ii<RSSI_STAT_COUNT;ii++) { | |
727 | if (pMgmt->pCurrBSS->ldBmAverage[ii] != 0) { | |
728 | pMgmt->pCurrBSS->ldBmMAX = max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm); | |
729 | } | |
730 | } | |
731 | } | |
732 | ||
733 | // ----------------------------------------------- | |
734 | ||
1b12068a | 735 | if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnable8021x == true)){ |
3fc9b584 | 736 | unsigned char abyMacHdr[24]; |
5449c685 FB |
737 | |
738 | // Only 802.1x packet incoming allowed | |
739 | if (bIsWEP) | |
740 | cbIVOffset = 8; | |
741 | else | |
742 | cbIVOffset = 0; | |
743 | wEtherType = (skb->data[cbIVOffset + 4 + 24 + 6] << 8) | | |
744 | skb->data[cbIVOffset + 4 + 24 + 6 + 1]; | |
745 | ||
7e809a9b | 746 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wEtherType = %04x \n", wEtherType); |
5449c685 FB |
747 | if (wEtherType == ETH_P_PAE) { |
748 | skb->dev = pDevice->apdev; | |
749 | ||
1b12068a | 750 | if (bIsWEP == true) { |
5449c685 FB |
751 | // strip IV header(8) |
752 | memcpy(&abyMacHdr[0], (skb->data + 4), 24); | |
753 | memcpy((skb->data + 4 + cbIVOffset), &abyMacHdr[0], 24); | |
754 | } | |
5449c685 FB |
755 | skb->data += (cbIVOffset + 4); |
756 | skb->tail += (cbIVOffset + 4); | |
757 | skb_put(skb, FrameSize); | |
db6cb903 | 758 | skb_reset_mac_header(skb); |
5449c685 FB |
759 | |
760 | skb->pkt_type = PACKET_OTHERHOST; | |
761 | skb->protocol = htons(ETH_P_802_2); | |
762 | memset(skb->cb, 0, sizeof(skb->cb)); | |
763 | netif_rx(skb); | |
1b12068a | 764 | return true; |
5449c685 FB |
765 | |
766 | } | |
767 | // check if 802.1x authorized | |
768 | if (!(pMgmt->sNodeDBTable[iSANodeIndex].dwFlags & WLAN_STA_AUTHORIZED)) | |
5a5a2a6a | 769 | return false; |
5449c685 FB |
770 | } |
771 | ||
772 | ||
773 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { | |
774 | if (bIsWEP) { | |
775 | FrameSize -= 8; //MIC | |
776 | } | |
777 | } | |
778 | ||
779 | //-------------------------------------------------------------------------------- | |
780 | // Soft MIC | |
781 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { | |
782 | if (bIsWEP) { | |
9d828c45 CC |
783 | unsigned long *pdwMIC_L; |
784 | unsigned long *pdwMIC_R; | |
0f4c60d6 CC |
785 | unsigned long dwMIC_Priority; |
786 | unsigned long dwMICKey0 = 0, dwMICKey1 = 0; | |
787 | unsigned long dwLocalMIC_L = 0; | |
788 | unsigned long dwLocalMIC_R = 0; | |
5449c685 FB |
789 | viawget_wpa_header *wpahdr; |
790 | ||
791 | ||
792 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { | |
9d828c45 CC |
793 | dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[24])); |
794 | dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[28])); | |
5449c685 FB |
795 | } |
796 | else { | |
797 | if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { | |
9d828c45 CC |
798 | dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[16])); |
799 | dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[20])); | |
5449c685 | 800 | } else if ((pKey->dwKeyIndex & BIT28) == 0) { |
9d828c45 CC |
801 | dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[16])); |
802 | dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[20])); | |
5449c685 | 803 | } else { |
9d828c45 CC |
804 | dwMICKey0 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[24])); |
805 | dwMICKey1 = cpu_to_le32(*(unsigned long *)(&pKey->abyKey[28])); | |
5449c685 FB |
806 | } |
807 | } | |
808 | ||
809 | MIC_vInit(dwMICKey0, dwMICKey1); | |
2989e96f | 810 | MIC_vAppend((unsigned char *)&(pDevice->sRxEthHeader.abyDstAddr[0]), 12); |
5449c685 | 811 | dwMIC_Priority = 0; |
2989e96f | 812 | MIC_vAppend((unsigned char *)&dwMIC_Priority, 4); |
5449c685 | 813 | // 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV. |
2989e96f | 814 | MIC_vAppend((unsigned char *)(skb->data + 4 + WLAN_HDR_ADDR3_LEN + 8), |
5449c685 FB |
815 | FrameSize - WLAN_HDR_ADDR3_LEN - 8); |
816 | MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R); | |
817 | MIC_vUnInit(); | |
818 | ||
9d828c45 CC |
819 | pdwMIC_L = (unsigned long *)(skb->data + 4 + FrameSize); |
820 | pdwMIC_R = (unsigned long *)(skb->data + 4 + FrameSize + 4); | |
5449c685 FB |
821 | //DBG_PRN_GRP12(("RxL: %lx, RxR: %lx\n", *pdwMIC_L, *pdwMIC_R)); |
822 | //DBG_PRN_GRP12(("LocalL: %lx, LocalR: %lx\n", dwLocalMIC_L, dwLocalMIC_R)); | |
7e809a9b | 823 | //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwMICKey0= %lx,dwMICKey1= %lx \n", dwMICKey0, dwMICKey1); |
5449c685 FB |
824 | |
825 | ||
826 | if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) || | |
1b12068a | 827 | (pDevice->bRxMICFail == true)) { |
7e809a9b | 828 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC comparison is fail!\n"); |
5a5a2a6a | 829 | pDevice->bRxMICFail = false; |
5449c685 FB |
830 | //pDevice->s802_11Counter.TKIPLocalMICFailures.QuadPart++; |
831 | pDevice->s802_11Counter.TKIPLocalMICFailures++; | |
832 | if (bDeFragRx) { | |
833 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
7e809a9b | 834 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", |
5449c685 FB |
835 | pDevice->dev->name); |
836 | } | |
837 | } | |
612822f5 | 838 | //2008-0409-07, <Add> by Einsn Liu |
5449c685 FB |
839 | #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT |
840 | //send event to wpa_supplicant | |
1b12068a | 841 | //if(pDevice->bWPADevEnable == true) |
612822f5 | 842 | { |
5449c685 FB |
843 | union iwreq_data wrqu; |
844 | struct iw_michaelmicfailure ev; | |
845 | int keyidx = pbyFrame[cbHeaderSize+3] >> 6; //top two-bits | |
846 | memset(&ev, 0, sizeof(ev)); | |
847 | ev.flags = keyidx & IW_MICFAILURE_KEY_ID; | |
848 | if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && | |
849 | (pMgmt->eCurrState == WMAC_STATE_ASSOC) && | |
850 | (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) { | |
851 | ev.flags |= IW_MICFAILURE_PAIRWISE; | |
852 | } else { | |
853 | ev.flags |= IW_MICFAILURE_GROUP; | |
854 | } | |
855 | ||
856 | ev.src_addr.sa_family = ARPHRD_ETHER; | |
857 | memcpy(ev.src_addr.sa_data, pMACHeader->abyAddr2, ETH_ALEN); | |
858 | memset(&wrqu, 0, sizeof(wrqu)); | |
859 | wrqu.data.length = sizeof(ev); | |
860 | wireless_send_event(pDevice->dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); | |
861 | ||
862 | } | |
863 | #endif | |
612822f5 JL |
864 | |
865 | ||
5449c685 FB |
866 | if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) { |
867 | wpahdr = (viawget_wpa_header *)pDevice->skb->data; | |
868 | if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && | |
869 | (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC) && | |
870 | (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) { | |
871 | //s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR; | |
872 | wpahdr->type = VIAWGET_PTK_MIC_MSG; | |
873 | } else { | |
874 | //s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_GROUP_ERROR; | |
875 | wpahdr->type = VIAWGET_GTK_MIC_MSG; | |
876 | } | |
877 | wpahdr->resp_ie_len = 0; | |
878 | wpahdr->req_ie_len = 0; | |
879 | skb_put(pDevice->skb, sizeof(viawget_wpa_header)); | |
880 | pDevice->skb->dev = pDevice->wpadev; | |
db6cb903 | 881 | skb_reset_mac_header(pDevice->skb); |
7bb8dc2d | 882 | pDevice->skb->pkt_type = PACKET_HOST; |
5449c685 FB |
883 | pDevice->skb->protocol = htons(ETH_P_802_2); |
884 | memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb)); | |
885 | netif_rx(pDevice->skb); | |
886 | pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); | |
9fc86028 | 887 | } |
5449c685 | 888 | |
5a5a2a6a | 889 | return false; |
5449c685 FB |
890 | |
891 | } | |
892 | } | |
893 | } //---end of SOFT MIC----------------------------------------------------------------------- | |
894 | ||
895 | // ++++++++++ Reply Counter Check +++++++++++++ | |
896 | ||
897 | if ((pKey != NULL) && ((pKey->byCipherSuite == KEY_CTL_TKIP) || | |
898 | (pKey->byCipherSuite == KEY_CTL_CCMP))) { | |
899 | if (bIsWEP) { | |
2986db5f | 900 | unsigned short wLocalTSC15_0 = 0; |
0f4c60d6 | 901 | unsigned long dwLocalTSC47_16 = 0; |
b2e876b6 | 902 | unsigned long long RSC = 0; |
5449c685 | 903 | // endian issues |
b2e876b6 | 904 | RSC = *((unsigned long long *) &(pKey->KeyRSC)); |
2986db5f | 905 | wLocalTSC15_0 = (unsigned short) RSC; |
0f4c60d6 | 906 | dwLocalTSC47_16 = (unsigned long) (RSC>>16); |
5449c685 FB |
907 | |
908 | RSC = dwRxTSC47_16; | |
909 | RSC <<= 16; | |
910 | RSC += wRxTSC15_0; | |
51b6d9c2 | 911 | memcpy(&(pKey->KeyRSC), &RSC, sizeof(QWORD)); |
5449c685 FB |
912 | |
913 | if ( (pDevice->sMgmtObj.eCurrMode == WMAC_MODE_ESS_STA) && | |
914 | (pDevice->sMgmtObj.eCurrState == WMAC_STATE_ASSOC)) { | |
915 | // check RSC | |
916 | if ( (wRxTSC15_0 < wLocalTSC15_0) && | |
917 | (dwRxTSC47_16 <= dwLocalTSC47_16) && | |
918 | !((dwRxTSC47_16 == 0) && (dwLocalTSC47_16 == 0xFFFFFFFF))) { | |
7e809a9b | 919 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC is illegal~~!\n "); |
5449c685 FB |
920 | if (pKey->byCipherSuite == KEY_CTL_TKIP) |
921 | //pDevice->s802_11Counter.TKIPReplays.QuadPart++; | |
922 | pDevice->s802_11Counter.TKIPReplays++; | |
923 | else | |
924 | //pDevice->s802_11Counter.CCMPReplays.QuadPart++; | |
925 | pDevice->s802_11Counter.CCMPReplays++; | |
926 | ||
927 | if (bDeFragRx) { | |
928 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
7e809a9b | 929 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", |
5449c685 FB |
930 | pDevice->dev->name); |
931 | } | |
932 | } | |
5a5a2a6a | 933 | return false; |
5449c685 FB |
934 | } |
935 | } | |
936 | } | |
937 | } // ----- End of Reply Counter Check -------------------------- | |
938 | ||
939 | ||
940 | ||
941 | if ((pKey != NULL) && (bIsWEP)) { | |
942 | // pDevice->s802_11Counter.DecryptSuccessCount.QuadPart++; | |
943 | } | |
944 | ||
945 | ||
2989e96f | 946 | s_vProcessRxMACHeader(pDevice, (unsigned char *)(skb->data+4), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset); |
5449c685 FB |
947 | FrameSize -= cbHeaderOffset; |
948 | cbHeaderOffset += 4; // 4 is Rcv buffer header | |
949 | ||
950 | // Null data, framesize = 14 | |
951 | if (FrameSize < 15) | |
5a5a2a6a | 952 | return false; |
5449c685 FB |
953 | |
954 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { | |
955 | if (s_bAPModeRxData(pDevice, | |
956 | skb, | |
957 | FrameSize, | |
958 | cbHeaderOffset, | |
959 | iSANodeIndex, | |
960 | iDANodeIndex | |
5a5a2a6a | 961 | ) == false) { |
5449c685 FB |
962 | |
963 | if (bDeFragRx) { | |
964 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
7e809a9b | 965 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", |
5449c685 FB |
966 | pDevice->dev->name); |
967 | } | |
968 | } | |
5a5a2a6a | 969 | return false; |
5449c685 FB |
970 | } |
971 | ||
5a5a2a6a | 972 | // if(pDevice->bRxMICFail == false) { |
5449c685 FB |
973 | // for (ii =0; ii < 100; ii++) |
974 | // printk(" %02x", *(skb->data + ii)); | |
975 | // printk("\n"); | |
976 | // } | |
977 | ||
978 | } | |
979 | ||
5449c685 FB |
980 | skb->data += cbHeaderOffset; |
981 | skb->tail += cbHeaderOffset; | |
982 | skb_put(skb, FrameSize); | |
983 | skb->protocol=eth_type_trans(skb, skb->dev); | |
5449c685 FB |
984 | |
985 | ||
986 | //drop frame not met IEEE 802.3 | |
987 | /* | |
988 | if (pDevice->flags & DEVICE_FLAGS_VAL_PKT_LEN) { | |
5449c685 FB |
989 | if ((skb->protocol==htons(ETH_P_802_3)) && |
990 | (skb->len!=htons(skb->mac.ethernet->h_proto))) { | |
5449c685 FB |
991 | pStats->rx_length_errors++; |
992 | pStats->rx_dropped++; | |
993 | if (bDeFragRx) { | |
994 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
7e809a9b | 995 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", |
5449c685 FB |
996 | pDevice->dev->name); |
997 | } | |
998 | } | |
5a5a2a6a | 999 | return false; |
5449c685 FB |
1000 | } |
1001 | } | |
1002 | */ | |
1003 | ||
5449c685 FB |
1004 | skb->ip_summed=CHECKSUM_NONE; |
1005 | pStats->rx_bytes +=skb->len; | |
1006 | pStats->rx_packets++; | |
1007 | netif_rx(skb); | |
5449c685 FB |
1008 | |
1009 | if (bDeFragRx) { | |
1010 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
7e809a9b | 1011 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", |
5449c685 FB |
1012 | pDevice->dev->name); |
1013 | } | |
5a5a2a6a | 1014 | return false; |
5449c685 | 1015 | } |
612822f5 | 1016 | |
1b12068a | 1017 | return true; |
5449c685 FB |
1018 | } |
1019 | ||
1020 | ||
7b6a0013 | 1021 | static bool s_bAPModeRxCtl ( |
3a215e0f | 1022 | PSDevice pDevice, |
2989e96f | 1023 | unsigned char *pbyFrame, |
7ca30195 | 1024 | int iSANodeIndex |
5449c685 FB |
1025 | ) |
1026 | { | |
1027 | PS802_11Header p802_11Header; | |
1028 | CMD_STATUS Status; | |
1029 | PSMgmtObject pMgmt = pDevice->pMgmt; | |
1030 | ||
1031 | ||
1032 | if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { | |
1033 | ||
1034 | p802_11Header = (PS802_11Header) (pbyFrame); | |
1035 | if (!IS_TYPE_MGMT(pbyFrame)) { | |
1036 | ||
1037 | // Data & PS-Poll packet | |
1038 | // check frame class | |
1039 | if (iSANodeIndex > 0) { | |
1040 | // frame class 3 fliter & checking | |
1041 | if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_AUTH) { | |
1042 | // send deauth notification | |
1043 | // reason = (6) class 2 received from nonauth sta | |
1044 | vMgrDeAuthenBeginSta(pDevice, | |
1045 | pMgmt, | |
2989e96f | 1046 | (unsigned char *)(p802_11Header->abyAddr2), |
5449c685 FB |
1047 | (WLAN_MGMT_REASON_CLASS2_NONAUTH), |
1048 | &Status | |
1049 | ); | |
7e809a9b | 1050 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 1\n"); |
1b12068a | 1051 | return true; |
9fc86028 | 1052 | } |
5449c685 FB |
1053 | if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_ASSOC) { |
1054 | // send deassoc notification | |
1055 | // reason = (7) class 3 received from nonassoc sta | |
1056 | vMgrDisassocBeginSta(pDevice, | |
1057 | pMgmt, | |
2989e96f | 1058 | (unsigned char *)(p802_11Header->abyAddr2), |
5449c685 FB |
1059 | (WLAN_MGMT_REASON_CLASS3_NONASSOC), |
1060 | &Status | |
1061 | ); | |
7e809a9b | 1062 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDisassocBeginSta 2\n"); |
1b12068a | 1063 | return true; |
9fc86028 | 1064 | } |
5449c685 FB |
1065 | |
1066 | if (pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable) { | |
1067 | // delcare received ps-poll event | |
1068 | if (IS_CTL_PSPOLL(pbyFrame)) { | |
1b12068a | 1069 | pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; |
e64354c0 | 1070 | bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL); |
7e809a9b | 1071 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 1\n"); |
5449c685 FB |
1072 | } |
1073 | else { | |
1074 | // check Data PS state | |
1075 | // if PW bit off, send out all PS bufferring packets. | |
1076 | if (!IS_FC_POWERMGT(pbyFrame)) { | |
5a5a2a6a | 1077 | pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false; |
1b12068a | 1078 | pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; |
e64354c0 | 1079 | bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL); |
7e809a9b | 1080 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 2\n"); |
5449c685 FB |
1081 | } |
1082 | } | |
1083 | } | |
1084 | else { | |
1085 | if (IS_FC_POWERMGT(pbyFrame)) { | |
1b12068a | 1086 | pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = true; |
5449c685 | 1087 | // Once if STA in PS state, enable multicast bufferring |
1b12068a | 1088 | pMgmt->sNodeDBTable[0].bPSEnable = true; |
5449c685 FB |
1089 | } |
1090 | else { | |
1091 | // clear all pending PS frame. | |
1092 | if (pMgmt->sNodeDBTable[iSANodeIndex].wEnQueueCnt > 0) { | |
5a5a2a6a | 1093 | pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false; |
1b12068a | 1094 | pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; |
e64354c0 | 1095 | bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL); |
7e809a9b | 1096 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 3\n"); |
5449c685 FB |
1097 | |
1098 | } | |
1099 | } | |
1100 | } | |
1101 | } | |
1102 | else { | |
1103 | vMgrDeAuthenBeginSta(pDevice, | |
1104 | pMgmt, | |
2989e96f | 1105 | (unsigned char *)(p802_11Header->abyAddr2), |
5449c685 FB |
1106 | (WLAN_MGMT_REASON_CLASS2_NONAUTH), |
1107 | &Status | |
1108 | ); | |
7e809a9b | 1109 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n"); |
30d6a2b8 AS |
1110 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n", |
1111 | p802_11Header->abyAddr3); | |
1112 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n", | |
1113 | p802_11Header->abyAddr2); | |
1114 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n", | |
1115 | p802_11Header->abyAddr1); | |
7e809a9b | 1116 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl ); |
5449c685 | 1117 | VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode)); |
7e809a9b | 1118 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc:pDevice->byRxMode = %x\n", pDevice->byRxMode ); |
1b12068a | 1119 | return true; |
5449c685 FB |
1120 | } |
1121 | } | |
1122 | } | |
5a5a2a6a | 1123 | return false; |
5449c685 FB |
1124 | |
1125 | } | |
1126 | ||
7b6a0013 | 1127 | static bool s_bHandleRxEncryption ( |
3a215e0f | 1128 | PSDevice pDevice, |
2989e96f | 1129 | unsigned char *pbyFrame, |
b6e95cd5 | 1130 | unsigned int FrameSize, |
2989e96f CC |
1131 | unsigned char *pbyRsr, |
1132 | unsigned char *pbyNewRsr, | |
3cdec554 | 1133 | PSKeyItem *pKeyOut, |
7b6a0013 | 1134 | bool *pbExtIV, |
15df6c2b | 1135 | unsigned short *pwRxTSC15_0, |
9d828c45 | 1136 | unsigned long *pdwRxTSC47_16 |
5449c685 FB |
1137 | ) |
1138 | { | |
b6e95cd5 | 1139 | unsigned int PayloadLen = FrameSize; |
2989e96f | 1140 | unsigned char *pbyIV; |
3fc9b584 | 1141 | unsigned char byKeyIdx; |
5449c685 | 1142 | PSKeyItem pKey = NULL; |
3fc9b584 | 1143 | unsigned char byDecMode = KEY_CTL_WEP; |
5449c685 FB |
1144 | PSMgmtObject pMgmt = pDevice->pMgmt; |
1145 | ||
1146 | ||
1147 | *pwRxTSC15_0 = 0; | |
1148 | *pdwRxTSC47_16 = 0; | |
1149 | ||
1150 | pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; | |
15df6c2b CC |
1151 | if ( WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) && |
1152 | WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame) ) { | |
5449c685 FB |
1153 | pbyIV += 6; // 6 is 802.11 address4 |
1154 | PayloadLen -= 6; | |
1155 | } | |
1156 | byKeyIdx = (*(pbyIV+3) & 0xc0); | |
1157 | byKeyIdx >>= 6; | |
7e809a9b | 1158 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx); |
5449c685 FB |
1159 | |
1160 | if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || | |
1161 | (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || | |
1162 | (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || | |
1163 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || | |
1164 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { | |
1165 | if (((*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) && | |
1166 | (pDevice->pMgmt->byCSSPK != KEY_CTL_NONE)) { | |
1167 | // unicast pkt use pairwise key | |
7e809a9b | 1168 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt\n"); |
1b12068a | 1169 | if (KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, 0xFFFFFFFF, &pKey) == true) { |
5449c685 FB |
1170 | if (pDevice->pMgmt->byCSSPK == KEY_CTL_TKIP) |
1171 | byDecMode = KEY_CTL_TKIP; | |
1172 | else if (pDevice->pMgmt->byCSSPK == KEY_CTL_CCMP) | |
1173 | byDecMode = KEY_CTL_CCMP; | |
1174 | } | |
7e809a9b | 1175 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt: %d, %p\n", byDecMode, pKey); |
5449c685 FB |
1176 | } else { |
1177 | // use group key | |
1178 | KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, byKeyIdx, &pKey); | |
1179 | if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP) | |
1180 | byDecMode = KEY_CTL_TKIP; | |
1181 | else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP) | |
1182 | byDecMode = KEY_CTL_CCMP; | |
7e809a9b | 1183 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"group pkt: %d, %d, %p\n", byKeyIdx, byDecMode, pKey); |
5449c685 FB |
1184 | } |
1185 | } | |
1186 | // our WEP only support Default Key | |
1187 | if (pKey == NULL) { | |
1188 | // use default group key | |
1189 | KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, byKeyIdx, &pKey); | |
1190 | if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP) | |
1191 | byDecMode = KEY_CTL_TKIP; | |
1192 | else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP) | |
1193 | byDecMode = KEY_CTL_CCMP; | |
1194 | } | |
1195 | *pKeyOut = pKey; | |
1196 | ||
7e809a9b | 1197 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pDevice->pMgmt->byCSSPK, pDevice->pMgmt->byCSSGK, byDecMode); |
5449c685 FB |
1198 | |
1199 | if (pKey == NULL) { | |
7e809a9b | 1200 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey == NULL\n"); |
5449c685 FB |
1201 | if (byDecMode == KEY_CTL_WEP) { |
1202 | // pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; | |
1b12068a | 1203 | } else if (pDevice->bLinkPass == true) { |
5449c685 FB |
1204 | // pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; |
1205 | } | |
5a5a2a6a | 1206 | return false; |
5449c685 FB |
1207 | } |
1208 | if (byDecMode != pKey->byCipherSuite) { | |
1209 | if (byDecMode == KEY_CTL_WEP) { | |
1210 | // pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; | |
1b12068a | 1211 | } else if (pDevice->bLinkPass == true) { |
5449c685 FB |
1212 | // pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; |
1213 | } | |
1214 | *pKeyOut = NULL; | |
5a5a2a6a | 1215 | return false; |
5449c685 FB |
1216 | } |
1217 | if (byDecMode == KEY_CTL_WEP) { | |
1218 | // handle WEP | |
1219 | if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || | |
1b12068a | 1220 | (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true)) { |
5449c685 FB |
1221 | // Software WEP |
1222 | // 1. 3253A | |
1223 | // 2. WEP 256 | |
1224 | ||
1225 | PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc | |
51b6d9c2 JL |
1226 | memcpy(pDevice->abyPRNG, pbyIV, 3); |
1227 | memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength); | |
5449c685 FB |
1228 | rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3); |
1229 | rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen); | |
1230 | ||
1231 | if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) { | |
1232 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
1233 | } | |
1234 | } | |
1235 | } else if ((byDecMode == KEY_CTL_TKIP) || | |
1236 | (byDecMode == KEY_CTL_CCMP)) { | |
1237 | // TKIP/AES | |
1238 | ||
1239 | PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc | |
9d828c45 | 1240 | *pdwRxTSC47_16 = cpu_to_le32(*(unsigned long *)(pbyIV + 4)); |
7e809a9b | 1241 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); |
5449c685 FB |
1242 | if (byDecMode == KEY_CTL_TKIP) { |
1243 | *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); | |
1244 | } else { | |
15df6c2b | 1245 | *pwRxTSC15_0 = cpu_to_le16(*(unsigned short *)pbyIV); |
5449c685 | 1246 | } |
7e809a9b | 1247 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); |
5449c685 FB |
1248 | |
1249 | if ((byDecMode == KEY_CTL_TKIP) && | |
1250 | (pDevice->byLocalID <= REV_ID_VT3253_A1)) { | |
1251 | // Software TKIP | |
1252 | // 1. 3253 A | |
1253 | PS802_11Header pMACHeader = (PS802_11Header) (pbyFrame); | |
1254 | TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG); | |
1255 | rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); | |
1256 | rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen); | |
1257 | if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) { | |
1258 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
7e809a9b | 1259 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n"); |
5449c685 | 1260 | } else { |
7e809a9b JL |
1261 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n"); |
1262 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen); | |
5449c685 FB |
1263 | } |
1264 | } | |
1265 | }// end of TKIP/AES | |
1266 | ||
1267 | if ((*(pbyIV+3) & 0x20) != 0) | |
1b12068a CC |
1268 | *pbExtIV = true; |
1269 | return true; | |
5449c685 FB |
1270 | } |
1271 | ||
1272 | ||
7b6a0013 | 1273 | static bool s_bHostWepRxEncryption ( |
3a215e0f | 1274 | PSDevice pDevice, |
2989e96f | 1275 | unsigned char *pbyFrame, |
b6e95cd5 | 1276 | unsigned int FrameSize, |
2989e96f | 1277 | unsigned char *pbyRsr, |
7b6a0013 | 1278 | bool bOnFly, |
3a215e0f | 1279 | PSKeyItem pKey, |
2989e96f | 1280 | unsigned char *pbyNewRsr, |
7b6a0013 | 1281 | bool *pbExtIV, |
15df6c2b | 1282 | unsigned short *pwRxTSC15_0, |
9d828c45 | 1283 | unsigned long *pdwRxTSC47_16 |
5449c685 FB |
1284 | ) |
1285 | { | |
b6e95cd5 | 1286 | unsigned int PayloadLen = FrameSize; |
2989e96f | 1287 | unsigned char *pbyIV; |
3fc9b584 CC |
1288 | unsigned char byKeyIdx; |
1289 | unsigned char byDecMode = KEY_CTL_WEP; | |
5449c685 FB |
1290 | PS802_11Header pMACHeader; |
1291 | ||
1292 | ||
1293 | ||
1294 | *pwRxTSC15_0 = 0; | |
1295 | *pdwRxTSC47_16 = 0; | |
1296 | ||
1297 | pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; | |
15df6c2b CC |
1298 | if ( WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) && |
1299 | WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame) ) { | |
5449c685 FB |
1300 | pbyIV += 6; // 6 is 802.11 address4 |
1301 | PayloadLen -= 6; | |
1302 | } | |
1303 | byKeyIdx = (*(pbyIV+3) & 0xc0); | |
1304 | byKeyIdx >>= 6; | |
7e809a9b | 1305 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx); |
5449c685 FB |
1306 | |
1307 | ||
1308 | if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP) | |
1309 | byDecMode = KEY_CTL_TKIP; | |
1310 | else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP) | |
1311 | byDecMode = KEY_CTL_CCMP; | |
1312 | ||
7e809a9b | 1313 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pDevice->pMgmt->byCSSPK, pDevice->pMgmt->byCSSGK, byDecMode); |
5449c685 FB |
1314 | |
1315 | if (byDecMode != pKey->byCipherSuite) { | |
1316 | if (byDecMode == KEY_CTL_WEP) { | |
1317 | // pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; | |
1b12068a | 1318 | } else if (pDevice->bLinkPass == true) { |
5449c685 FB |
1319 | // pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; |
1320 | } | |
5a5a2a6a | 1321 | return false; |
5449c685 FB |
1322 | } |
1323 | ||
1324 | if (byDecMode == KEY_CTL_WEP) { | |
1325 | // handle WEP | |
7e809a9b | 1326 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byDecMode == KEY_CTL_WEP \n"); |
5449c685 | 1327 | if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || |
1b12068a | 1328 | (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true) || |
5a5a2a6a | 1329 | (bOnFly == false)) { |
5449c685 FB |
1330 | // Software WEP |
1331 | // 1. 3253A | |
1332 | // 2. WEP 256 | |
1333 | // 3. NotOnFly | |
1334 | ||
1335 | PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc | |
51b6d9c2 JL |
1336 | memcpy(pDevice->abyPRNG, pbyIV, 3); |
1337 | memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength); | |
5449c685 FB |
1338 | rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3); |
1339 | rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen); | |
1340 | ||
1341 | if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) { | |
1342 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
1343 | } | |
1344 | } | |
1345 | } else if ((byDecMode == KEY_CTL_TKIP) || | |
1346 | (byDecMode == KEY_CTL_CCMP)) { | |
1347 | // TKIP/AES | |
1348 | ||
1349 | PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc | |
9d828c45 | 1350 | *pdwRxTSC47_16 = cpu_to_le32(*(unsigned long *)(pbyIV + 4)); |
7e809a9b | 1351 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); |
5449c685 FB |
1352 | |
1353 | if (byDecMode == KEY_CTL_TKIP) { | |
1354 | *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); | |
1355 | } else { | |
15df6c2b | 1356 | *pwRxTSC15_0 = cpu_to_le16(*(unsigned short *)pbyIV); |
5449c685 | 1357 | } |
7e809a9b | 1358 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); |
5449c685 FB |
1359 | |
1360 | if (byDecMode == KEY_CTL_TKIP) { | |
612822f5 | 1361 | |
5a5a2a6a | 1362 | if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || (bOnFly == false)) { |
5449c685 FB |
1363 | // Software TKIP |
1364 | // 1. 3253 A | |
1365 | // 2. NotOnFly | |
7e809a9b | 1366 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_TKIP \n"); |
5449c685 FB |
1367 | pMACHeader = (PS802_11Header) (pbyFrame); |
1368 | TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG); | |
1369 | rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); | |
1370 | rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen); | |
1371 | if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) { | |
1372 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
7e809a9b | 1373 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n"); |
5449c685 | 1374 | } else { |
7e809a9b JL |
1375 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n"); |
1376 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen); | |
5449c685 FB |
1377 | } |
1378 | } | |
1379 | } | |
1380 | ||
1381 | if (byDecMode == KEY_CTL_CCMP) { | |
5a5a2a6a | 1382 | if (bOnFly == false) { |
5449c685 FB |
1383 | // Software CCMP |
1384 | // NotOnFly | |
7e809a9b | 1385 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_CCMP\n"); |
5449c685 FB |
1386 | if (AESbGenCCMP(pKey->abyKey, pbyFrame, FrameSize)) { |
1387 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
7e809a9b | 1388 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CCMP MIC compare OK!\n"); |
5449c685 | 1389 | } else { |
7e809a9b | 1390 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CCMP MIC fail!\n"); |
5449c685 FB |
1391 | } |
1392 | } | |
1393 | } | |
1394 | ||
1395 | }// end of TKIP/AES | |
1396 | ||
1397 | if ((*(pbyIV+3) & 0x20) != 0) | |
1b12068a CC |
1398 | *pbExtIV = true; |
1399 | return true; | |
5449c685 FB |
1400 | } |
1401 | ||
1402 | ||
1403 | ||
7b6a0013 | 1404 | static bool s_bAPModeRxData ( |
3a215e0f CC |
1405 | PSDevice pDevice, |
1406 | struct sk_buff* skb, | |
b6e95cd5 CC |
1407 | unsigned int FrameSize, |
1408 | unsigned int cbHeaderOffset, | |
7ca30195 CC |
1409 | int iSANodeIndex, |
1410 | int iDANodeIndex | |
5449c685 | 1411 | ) |
5449c685 FB |
1412 | { |
1413 | PSMgmtObject pMgmt = pDevice->pMgmt; | |
7b6a0013 CC |
1414 | bool bRelayAndForward = false; |
1415 | bool bRelayOnly = false; | |
3fc9b584 | 1416 | unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; |
2986db5f | 1417 | unsigned short wAID; |
5449c685 FB |
1418 | |
1419 | ||
612822f5 | 1420 | struct sk_buff* skbcpy = NULL; |
5449c685 FB |
1421 | |
1422 | if (FrameSize > CB_MAX_BUF_SIZE) | |
5a5a2a6a | 1423 | return false; |
5449c685 | 1424 | // check DA |
2989e96f | 1425 | if(is_multicast_ether_addr((unsigned char *)(skb->data+cbHeaderOffset))) { |
5449c685 FB |
1426 | if (pMgmt->sNodeDBTable[0].bPSEnable) { |
1427 | ||
5449c685 | 1428 | skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz); |
612822f5 | 1429 | |
5449c685 FB |
1430 | // if any node in PS mode, buffer packet until DTIM. |
1431 | if (skbcpy == NULL) { | |
7e809a9b | 1432 | DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n"); |
5449c685 FB |
1433 | } |
1434 | else { | |
1435 | skbcpy->dev = pDevice->dev; | |
5449c685 FB |
1436 | skbcpy->len = FrameSize; |
1437 | memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize); | |
1438 | skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy); | |
612822f5 | 1439 | |
5449c685 FB |
1440 | pMgmt->sNodeDBTable[0].wEnQueueCnt++; |
1441 | // set tx map | |
1442 | pMgmt->abyPSTxMap[0] |= byMask[0]; | |
1443 | } | |
1444 | } | |
1445 | else { | |
1b12068a | 1446 | bRelayAndForward = true; |
5449c685 FB |
1447 | } |
1448 | } | |
1449 | else { | |
1450 | // check if relay | |
2989e96f | 1451 | if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data+cbHeaderOffset), &iDANodeIndex)) { |
5449c685 FB |
1452 | if (pMgmt->sNodeDBTable[iDANodeIndex].eNodeState >= NODE_ASSOC) { |
1453 | if (pMgmt->sNodeDBTable[iDANodeIndex].bPSEnable) { | |
1454 | // queue this skb until next PS tx, and then release. | |
1455 | ||
5449c685 FB |
1456 | skb->data += cbHeaderOffset; |
1457 | skb->tail += cbHeaderOffset; | |
1458 | skb_put(skb, FrameSize); | |
1459 | skb_queue_tail(&pMgmt->sNodeDBTable[iDANodeIndex].sTxPSQueue, skb); | |
5449c685 FB |
1460 | pMgmt->sNodeDBTable[iDANodeIndex].wEnQueueCnt++; |
1461 | wAID = pMgmt->sNodeDBTable[iDANodeIndex].wAID; | |
1462 | pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; | |
7e809a9b | 1463 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "relay: index= %d, pMgmt->abyPSTxMap[%d]= %d\n", |
5449c685 | 1464 | iDANodeIndex, (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]); |
1b12068a | 1465 | return true; |
5449c685 FB |
1466 | } |
1467 | else { | |
1b12068a | 1468 | bRelayOnly = true; |
5449c685 FB |
1469 | } |
1470 | } | |
9fc86028 | 1471 | } |
5449c685 FB |
1472 | } |
1473 | ||
1474 | if (bRelayOnly || bRelayAndForward) { | |
1475 | // relay this packet right now | |
1476 | if (bRelayAndForward) | |
1477 | iDANodeIndex = 0; | |
1478 | ||
1479 | if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) { | |
2989e96f | 1480 | ROUTEbRelay(pDevice, (unsigned char *)(skb->data + cbHeaderOffset), FrameSize, (unsigned int)iDANodeIndex); |
5449c685 FB |
1481 | } |
1482 | ||
1483 | if (bRelayOnly) | |
5a5a2a6a | 1484 | return false; |
5449c685 FB |
1485 | } |
1486 | // none associate, don't forward | |
1487 | if (pDevice->uAssocCount == 0) | |
5a5a2a6a | 1488 | return false; |
5449c685 | 1489 | |
1b12068a | 1490 | return true; |
5449c685 FB |
1491 | } |
1492 |