]>
Commit | Line | Data |
---|---|---|
36c7928c BZ |
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 | } |