]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/rt2860/sta/sanity.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[mv-sheeva.git] / drivers / staging / rt2860 / 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         Justin P. Mattock       11/07/2010      Fix typos
37 */
38 #include "../rt_config.h"
39
40 extern u8 CISCO_OUI[];
41
42 extern u8 WPA_OUI[];
43 extern u8 RSN_OUI[];
44 extern u8 WME_INFO_ELEM[];
45 extern u8 WME_PARM_ELEM[];
46 extern u8 Ccx2QosInfo[];
47 extern u8 RALINK_OUI[];
48 extern u8 BROADCOM_OUI[];
49
50 /*
51     ==========================================================================
52     Description:
53         MLME message sanity check
54     Return:
55         TRUE if all parameters are OK, FALSE otherwise
56     ==========================================================================
57  */
58 BOOLEAN MlmeStartReqSanity(struct rt_rtmp_adapter *pAd,
59                            void * Msg,
60                            unsigned long MsgLen,
61                            char Ssid[], u8 * pSsidLen)
62 {
63         struct rt_mlme_start_req *Info;
64
65         Info = (struct rt_mlme_start_req *)(Msg);
66
67         if (Info->SsidLen > MAX_LEN_OF_SSID) {
68                 DBGPRINT(RT_DEBUG_TRACE,
69                          ("MlmeStartReqSanity fail - wrong SSID length\n"));
70                 return FALSE;
71         }
72
73         *pSsidLen = Info->SsidLen;
74         NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen);
75
76         return TRUE;
77 }
78
79 /*
80     ==========================================================================
81     Description:
82         MLME message sanity check
83     Return:
84         TRUE if all parameters are OK, FALSE otherwise
85
86     IRQL = DISPATCH_LEVEL
87
88     ==========================================================================
89  */
90 BOOLEAN PeerAssocRspSanity(struct rt_rtmp_adapter *pAd, void * pMsg, unsigned long MsgLen, u8 *pAddr2, u16 * pCapabilityInfo, u16 * pStatus, u16 * pAid, u8 SupRate[], u8 * pSupRateLen, u8 ExtRate[], u8 * pExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo,     /* AP might use this additional ht info IE */
91                            u8 * pHtCapabilityLen,
92                            u8 * pAddHtInfoLen,
93                            u8 * pNewExtChannelOffset,
94                            struct rt_edca_parm *pEdcaParm, u8 * pCkipFlag)
95 {
96         char IeType, *Ptr;
97         struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) pMsg;
98         struct rt_eid * pEid;
99         unsigned long Length = 0;
100
101         *pNewExtChannelOffset = 0xff;
102         *pHtCapabilityLen = 0;
103         *pAddHtInfoLen = 0;
104         COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
105         Ptr = (char *)pFrame->Octet;
106         Length += LENGTH_802_11;
107
108         NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2);
109         Length += 2;
110         NdisMoveMemory(pStatus, &pFrame->Octet[2], 2);
111         Length += 2;
112         *pCkipFlag = 0;
113         *pExtRateLen = 0;
114         pEdcaParm->bValid = FALSE;
115
116         if (*pStatus != MLME_SUCCESS)
117                 return TRUE;
118
119         NdisMoveMemory(pAid, &pFrame->Octet[4], 2);
120         Length += 2;
121
122         /* Aid already swapped byte order in RTMPFrameEndianChange() for big endian platform */
123         *pAid = (*pAid) & 0x3fff;       /* AID is low 14-bit */
124
125         /* -- get supported rates from payload and advance the pointer */
126         IeType = pFrame->Octet[6];
127         *pSupRateLen = pFrame->Octet[7];
128         if ((IeType != IE_SUPP_RATES)
129             || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) {
130                 DBGPRINT(RT_DEBUG_TRACE,
131                          ("PeerAssocRspSanity fail - wrong SupportedRates IE\n"));
132                 return FALSE;
133         } else
134                 NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen);
135
136         Length = Length + 2 + *pSupRateLen;
137
138         /* many AP implement proprietary IEs in non-standard order, we'd better */
139         /* tolerate mis-ordered IEs to get best compatibility */
140         pEid = (struct rt_eid *) & pFrame->Octet[8 + (*pSupRateLen)];
141
142         /* get variable fields from payload and advance the pointer */
143         while ((Length + 2 + pEid->Len) <= MsgLen) {
144                 switch (pEid->Eid) {
145                 case IE_EXT_SUPP_RATES:
146                         if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) {
147                                 NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
148                                 *pExtRateLen = pEid->Len;
149                         }
150                         break;
151
152                 case IE_HT_CAP:
153                 case IE_HT_CAP2:
154                         if (pEid->Len >= SIZE_HT_CAP_IE)        /*Note: allow extension! */
155                         {
156                                 NdisMoveMemory(pHtCapability, pEid->Octet,
157                                                SIZE_HT_CAP_IE);
158
159                                 *(u16 *) (&pHtCapability->HtCapInfo) =
160                                     cpu2le16(*(u16 *)
161                                              (&pHtCapability->HtCapInfo));
162                                 *(u16 *) (&pHtCapability->ExtHtCapInfo) =
163                                     cpu2le16(*(u16 *)
164                                              (&pHtCapability->ExtHtCapInfo));
165
166                                 *pHtCapabilityLen = SIZE_HT_CAP_IE;
167                         } else {
168                                 DBGPRINT(RT_DEBUG_WARN,
169                                          ("PeerAssocRspSanity - wrong IE_HT_CAP. \n"));
170                         }
171
172                         break;
173                 case IE_ADD_HT:
174                 case IE_ADD_HT2:
175                         if (pEid->Len >= sizeof(struct rt_add_ht_info_ie)) {
176                                 /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */
177                                 /* copy first sizeof(struct rt_add_ht_info_ie) */
178                                 NdisMoveMemory(pAddHtInfo, pEid->Octet,
179                                                sizeof(struct rt_add_ht_info_ie));
180
181                                 *(u16 *) (&pAddHtInfo->AddHtInfo2) =
182                                     cpu2le16(*(u16 *)
183                                              (&pAddHtInfo->AddHtInfo2));
184                                 *(u16 *) (&pAddHtInfo->AddHtInfo3) =
185                                     cpu2le16(*(u16 *)
186                                              (&pAddHtInfo->AddHtInfo3));
187
188                                 *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE;
189                         } else {
190                                 DBGPRINT(RT_DEBUG_WARN,
191                                          ("PeerAssocRspSanity - wrong IE_ADD_HT. \n"));
192                         }
193
194                         break;
195                 case IE_SECONDARY_CH_OFFSET:
196                         if (pEid->Len == 1) {
197                                 *pNewExtChannelOffset = pEid->Octet[0];
198                         } else {
199                                 DBGPRINT(RT_DEBUG_WARN,
200                                          ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n"));
201                         }
202                         break;
203
204                 case IE_VENDOR_SPECIFIC:
205                         /* handle WME PARAMTER ELEMENT */
206                         if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6)
207                             && (pEid->Len == 24)) {
208                                 u8 *ptr;
209                                 int i;
210
211                                 /* parsing EDCA parameters */
212                                 pEdcaParm->bValid = TRUE;
213                                 pEdcaParm->bQAck = FALSE;       /* pEid->Octet[0] & 0x10; */
214                                 pEdcaParm->bQueueRequest = FALSE;       /* pEid->Octet[0] & 0x20; */
215                                 pEdcaParm->bTxopRequest = FALSE;        /* pEid->Octet[0] & 0x40; */
216                                 /*pEdcaParm->bMoreDataAck    = FALSE; // pEid->Octet[0] & 0x80; */
217                                 pEdcaParm->EdcaUpdateCount =
218                                     pEid->Octet[6] & 0x0f;
219                                 pEdcaParm->bAPSDCapable =
220                                     (pEid->Octet[6] & 0x80) ? 1 : 0;
221                                 ptr = (u8 *)& pEid->Octet[8];
222                                 for (i = 0; i < 4; i++) {
223                                         u8 aci = (*ptr & 0x60) >> 5;    /* b5~6 is AC INDEX */
224                                         pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10);       /* b5 is ACM */
225                                         pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f;  /* b0~3 is AIFSN */
226                                         pEdcaParm->Cwmin[aci] = *(ptr + 1) & 0x0f;      /* b0~4 is Cwmin */
227                                         pEdcaParm->Cwmax[aci] = *(ptr + 1) >> 4;        /* b5~8 is Cwmax */
228                                         pEdcaParm->Txop[aci] = *(ptr + 2) + 256 * (*(ptr + 3)); /* in unit of 32-us */
229                                         ptr += 4;       /* point to next AC */
230                                 }
231                         }
232                         break;
233                 default:
234                         DBGPRINT(RT_DEBUG_TRACE,
235                                  ("PeerAssocRspSanity - ignore unrecognized EID = %d\n",
236                                   pEid->Eid));
237                         break;
238                 }
239
240                 Length = Length + 2 + pEid->Len;
241                 pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len);
242         }
243
244         return TRUE;
245 }
246
247 /*
248     ==========================================================================
249     Description:
250         MLME message sanity check
251     Return:
252         TRUE if all parameters are OK, FALSE otherwise
253
254         IRQL = DISPATCH_LEVEL
255
256     ==========================================================================
257  */
258 BOOLEAN PeerProbeReqSanity(struct rt_rtmp_adapter *pAd,
259                            void * Msg,
260                            unsigned long MsgLen,
261                            u8 *pAddr2,
262                            char Ssid[], u8 * pSsidLen)
263 {
264         u8 Idx;
265         u8 RateLen;
266         char IeType;
267         struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg;
268
269         COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
270
271         if ((pFrame->Octet[0] != IE_SSID)
272             || (pFrame->Octet[1] > MAX_LEN_OF_SSID)) {
273                 DBGPRINT(RT_DEBUG_TRACE,
274                          ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",
275                           pFrame->Octet[0], pFrame->Octet[1]));
276                 return FALSE;
277         }
278
279         *pSsidLen = pFrame->Octet[1];
280         NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen);
281
282         Idx = *pSsidLen + 2;
283
284         /* -- get supported rates from payload and advance the pointer */
285         IeType = pFrame->Octet[Idx];
286         RateLen = pFrame->Octet[Idx + 1];
287         if (IeType != IE_SUPP_RATES) {
288                 DBGPRINT(RT_DEBUG_TRACE,
289                          ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",
290                           pFrame->Octet[Idx], pFrame->Octet[Idx + 1]));
291                 return FALSE;
292         } else {
293                 if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8))
294                         return (FALSE);
295         }
296
297         return TRUE;
298 }
299
300 /*
301     ==========================================================================
302     Description:
303
304         IRQL = DISPATCH_LEVEL
305
306     ==========================================================================
307  */
308 BOOLEAN GetTimBit(char * Ptr,
309                   u16 Aid,
310                   u8 * TimLen,
311                   u8 * BcastFlag,
312                   u8 * DtimCount,
313                   u8 * DtimPeriod, u8 * MessageToMe)
314 {
315         u8 BitCntl, N1, N2, MyByte, MyBit;
316         char *IdxPtr;
317
318         IdxPtr = Ptr;
319
320         IdxPtr++;
321         *TimLen = *IdxPtr;
322
323         /* get DTIM Count from TIM element */
324         IdxPtr++;
325         *DtimCount = *IdxPtr;
326
327         /* get DTIM Period from TIM element */
328         IdxPtr++;
329         *DtimPeriod = *IdxPtr;
330
331         /* get Bitmap Control from TIM element */
332         IdxPtr++;
333         BitCntl = *IdxPtr;
334
335         if ((*DtimCount == 0) && (BitCntl & 0x01))
336                 *BcastFlag = TRUE;
337         else
338                 *BcastFlag = FALSE;
339
340         /* Parse Partial Virtual Bitmap from TIM element */
341         N1 = BitCntl & 0xfe;    /* N1 is the first bitmap byte# */
342         N2 = *TimLen - 4 + N1;  /* N2 is the last bitmap byte# */
343
344         if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3)))
345                 *MessageToMe = FALSE;
346         else {
347                 MyByte = (Aid >> 3) - N1;       /* my byte position in the bitmap byte-stream */
348                 MyBit = Aid % 16 - ((MyByte & 0x01) ? 8 : 0);
349
350                 IdxPtr += (MyByte + 1);
351
352                 /*if (*IdxPtr) */
353                 /*    DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr)); */
354
355                 if (*IdxPtr & (0x01 << MyBit))
356                         *MessageToMe = TRUE;
357                 else
358                         *MessageToMe = FALSE;
359         }
360
361         return TRUE;
362 }