]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/rt3090/sta/sanity.c
Staging: add rt3090 wireless driver
[mv-sheeva.git] / drivers / staging / rt3090 / sta / sanity.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27         Module Name:
28         sanity.c
29
30         Abstract:
31
32         Revision History:
33         Who                     When                    What
34         --------        ----------              ----------------------------------------------
35         John Chang  2004-09-01      add WMM support
36 */
37
38 #include "../rt_config.h"
39
40
41 extern UCHAR    CISCO_OUI[];
42
43 extern UCHAR    WPA_OUI[];
44 extern UCHAR    RSN_OUI[];
45 extern UCHAR    WME_INFO_ELEM[];
46 extern UCHAR    WME_PARM_ELEM[];
47 extern UCHAR    Ccx2QosInfo[];
48 extern UCHAR    RALINK_OUI[];
49 extern UCHAR    BROADCOM_OUI[];
50
51 /*
52     ==========================================================================
53     Description:
54         MLME message sanity check
55     Return:
56         TRUE if all parameters are OK, FALSE otherwise
57     ==========================================================================
58  */
59 BOOLEAN MlmeStartReqSanity(
60     IN PRTMP_ADAPTER pAd,
61     IN VOID *Msg,
62     IN ULONG MsgLen,
63     OUT CHAR Ssid[],
64     OUT UCHAR *pSsidLen)
65 {
66     MLME_START_REQ_STRUCT *Info;
67
68     Info = (MLME_START_REQ_STRUCT *)(Msg);
69
70     if (Info->SsidLen > MAX_LEN_OF_SSID)
71     {
72         DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqSanity fail - wrong SSID length\n"));
73         return FALSE;
74     }
75
76     *pSsidLen = Info->SsidLen;
77     NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen);
78
79     return TRUE;
80 }
81
82 /*
83     ==========================================================================
84     Description:
85         MLME message sanity check
86     Return:
87         TRUE if all parameters are OK, FALSE otherwise
88
89     IRQL = DISPATCH_LEVEL
90
91     ==========================================================================
92  */
93 BOOLEAN PeerAssocRspSanity(
94     IN PRTMP_ADAPTER pAd,
95     IN VOID *pMsg,
96     IN ULONG MsgLen,
97     OUT PUCHAR pAddr2,
98     OUT USHORT *pCapabilityInfo,
99     OUT USHORT *pStatus,
100     OUT USHORT *pAid,
101     OUT UCHAR SupRate[],
102     OUT UCHAR *pSupRateLen,
103     OUT UCHAR ExtRate[],
104     OUT UCHAR *pExtRateLen,
105     OUT HT_CAPABILITY_IE                *pHtCapability,
106     OUT ADD_HT_INFO_IE          *pAddHtInfo,    // AP might use this additional ht info IE
107     OUT UCHAR                   *pHtCapabilityLen,
108     OUT UCHAR                   *pAddHtInfoLen,
109     OUT UCHAR                   *pNewExtChannelOffset,
110     OUT PEDCA_PARM pEdcaParm,
111     OUT UCHAR *pCkipFlag)
112 {
113     CHAR          IeType, *Ptr;
114     PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
115     PEID_STRUCT   pEid;
116     ULONG         Length = 0;
117
118         *pNewExtChannelOffset = 0xff;
119         *pHtCapabilityLen = 0;
120         *pAddHtInfoLen = 0;
121     COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
122     Ptr = (PCHAR)pFrame->Octet;
123     Length += LENGTH_802_11;
124
125     NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2);
126     Length += 2;
127     NdisMoveMemory(pStatus,         &pFrame->Octet[2], 2);
128     Length += 2;
129     *pCkipFlag = 0;
130     *pExtRateLen = 0;
131     pEdcaParm->bValid = FALSE;
132
133     if (*pStatus != MLME_SUCCESS)
134         return TRUE;
135
136     NdisMoveMemory(pAid, &pFrame->Octet[4], 2);
137     Length += 2;
138
139     // Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform
140     *pAid = (*pAid) & 0x3fff; // AID is low 14-bit
141
142     // -- get supported rates from payload and advance the pointer
143     IeType = pFrame->Octet[6];
144     *pSupRateLen = pFrame->Octet[7];
145     if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES))
146     {
147         DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n"));
148         return FALSE;
149     }
150     else
151         NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen);
152
153
154     Length = Length + 2 + *pSupRateLen;
155
156     // many AP implement proprietary IEs in non-standard order, we'd better
157     // tolerate mis-ordered IEs to get best compatibility
158     pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)];
159
160     // get variable fields from payload and advance the pointer
161     while ((Length + 2 + pEid->Len) <= MsgLen)
162     {
163         switch (pEid->Eid)
164         {
165             case IE_EXT_SUPP_RATES:
166                 if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
167                 {
168                     NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
169                     *pExtRateLen = pEid->Len;
170                 }
171                 break;
172
173              case IE_HT_CAP:
174             case IE_HT_CAP2:
175                         if (pEid->Len >= SIZE_HT_CAP_IE)  //Note: allow extension.!!
176                         {
177                                 NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE);
178
179                                 *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
180                                 *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
181
182                                 *pHtCapabilityLen = SIZE_HT_CAP_IE;
183                         }
184                         else
185                         {
186                                 DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n"));
187                         }
188
189                 break;
190 #ifdef DOT11_N_SUPPORT
191             case IE_ADD_HT:
192             case IE_ADD_HT2:
193                         if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
194                         {
195                                 // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only
196                                 // copy first sizeof(ADD_HT_INFO_IE)
197                                 NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
198
199                                 *(USHORT *)(&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2));
200                                 *(USHORT *)(&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3));
201
202                                 *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE;
203                         }
204                         else
205                         {
206                                 DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n"));
207                         }
208
209                 break;
210             case IE_SECONDARY_CH_OFFSET:
211                         if (pEid->Len == 1)
212                         {
213                                 *pNewExtChannelOffset = pEid->Octet[0];
214                         }
215                         else
216                         {
217                                 DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n"));
218                         }
219 #endif // DOT11_N_SUPPORT //
220                 break;
221
222             case IE_VENDOR_SPECIFIC:
223                 // handle WME PARAMTER ELEMENT
224                 if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
225                 {
226                     PUCHAR ptr;
227                     int i;
228
229                     // parsing EDCA parameters
230                     pEdcaParm->bValid          = TRUE;
231                     pEdcaParm->bQAck           = FALSE; // pEid->Octet[0] & 0x10;
232                     pEdcaParm->bQueueRequest   = FALSE; // pEid->Octet[0] & 0x20;
233                     pEdcaParm->bTxopRequest    = FALSE; // pEid->Octet[0] & 0x40;
234                     //pEdcaParm->bMoreDataAck    = FALSE; // pEid->Octet[0] & 0x80;
235                     pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
236                     pEdcaParm->bAPSDCapable    = (pEid->Octet[6] & 0x80) ? 1 : 0;
237                     ptr = (PUCHAR)&pEid->Octet[8];
238                     for (i=0; i<4; i++)
239                     {
240                         UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX
241                         pEdcaParm->bACM[aci]  = (((*ptr) & 0x10) == 0x10);   // b5 is ACM
242                         pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f;               // b0~3 is AIFSN
243                         pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f;             // b0~4 is Cwmin
244                         pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4;               // b5~8 is Cwmax
245                         pEdcaParm->Txop[aci]  = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us
246                         ptr += 4; // point to next AC
247                     }
248                 }
249                 break;
250             default:
251                 DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid));
252                 break;
253         }
254
255         Length = Length + 2 + pEid->Len;
256         pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
257     }
258
259
260     return TRUE;
261 }
262
263 /*
264     ==========================================================================
265     Description:
266         MLME message sanity check
267     Return:
268         TRUE if all parameters are OK, FALSE otherwise
269
270         IRQL = DISPATCH_LEVEL
271
272     ==========================================================================
273  */
274 BOOLEAN PeerProbeReqSanity(
275     IN PRTMP_ADAPTER pAd,
276     IN VOID *Msg,
277     IN ULONG MsgLen,
278     OUT PUCHAR pAddr2,
279     OUT CHAR Ssid[],
280     OUT UCHAR *pSsidLen)
281 {
282     UCHAR         Idx;
283     UCHAR             RateLen;
284     CHAR          IeType;
285     PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
286
287     COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
288
289     if ((pFrame->Octet[0] != IE_SSID) || (pFrame->Octet[1] > MAX_LEN_OF_SSID))
290     {
291         DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",pFrame->Octet[0],pFrame->Octet[1]));
292         return FALSE;
293     }
294
295     *pSsidLen = pFrame->Octet[1];
296     NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen);
297
298     Idx = *pSsidLen + 2;
299
300     // -- get supported rates from payload and advance the pointer
301     IeType = pFrame->Octet[Idx];
302     RateLen = pFrame->Octet[Idx + 1];
303     if (IeType != IE_SUPP_RATES)
304     {
305         DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",pFrame->Octet[Idx],pFrame->Octet[Idx+1]));
306         return FALSE;
307     }
308     else
309     {
310         if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8))
311             return (FALSE);
312     }
313
314     return TRUE;
315 }
316
317 /*
318     ==========================================================================
319     Description:
320
321         IRQL = DISPATCH_LEVEL
322
323     ==========================================================================
324  */
325 BOOLEAN GetTimBit(
326     IN CHAR *Ptr,
327     IN USHORT Aid,
328     OUT UCHAR *TimLen,
329     OUT UCHAR *BcastFlag,
330     OUT UCHAR *DtimCount,
331     OUT UCHAR *DtimPeriod,
332     OUT UCHAR *MessageToMe)
333 {
334     UCHAR          BitCntl, N1, N2, MyByte, MyBit;
335     CHAR          *IdxPtr;
336
337     IdxPtr = Ptr;
338
339     IdxPtr ++;
340     *TimLen = *IdxPtr;
341
342     // get DTIM Count from TIM element
343     IdxPtr ++;
344     *DtimCount = *IdxPtr;
345
346     // get DTIM Period from TIM element
347     IdxPtr++;
348     *DtimPeriod = *IdxPtr;
349
350     // get Bitmap Control from TIM element
351     IdxPtr++;
352     BitCntl = *IdxPtr;
353
354     if ((*DtimCount == 0) && (BitCntl & 0x01))
355         *BcastFlag = TRUE;
356     else
357         *BcastFlag = FALSE;
358
359     // Parse Partial Virtual Bitmap from TIM element
360     N1 = BitCntl & 0xfe;    // N1 is the first bitmap byte#
361     N2 = *TimLen - 4 + N1;  // N2 is the last bitmap byte#
362
363     if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3)))
364         *MessageToMe = FALSE;
365     else
366     {
367         MyByte = (Aid >> 3) - N1;                       // my byte position in the bitmap byte-stream
368         MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0);
369
370         IdxPtr += (MyByte + 1);
371
372         //if (*IdxPtr)
373         //    DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr));
374
375         if (*IdxPtr & (0x01 << MyBit))
376             *MessageToMe = TRUE;
377         else
378             *MessageToMe = FALSE;
379     }
380
381     return TRUE;
382 }