]>
Commit | Line | Data |
---|---|---|
91980990 GKH |
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 | #include "../rt_config.h" | |
38 | ||
51126deb | 39 | extern u8 CISCO_OUI[]; |
91980990 | 40 | |
51126deb BZ |
41 | extern u8 WPA_OUI[]; |
42 | extern u8 RSN_OUI[]; | |
43 | extern u8 WME_INFO_ELEM[]; | |
44 | extern u8 WME_PARM_ELEM[]; | |
45 | extern u8 Ccx2QosInfo[]; | |
46 | extern u8 RALINK_OUI[]; | |
47 | extern u8 BROADCOM_OUI[]; | |
48 | extern u8 WPS_OUI[]; | |
91980990 GKH |
49 | |
50 | /* | |
51 | ========================================================================== | |
52 | Description: | |
53 | MLME message sanity check | |
54 | Return: | |
55 | TRUE if all parameters are OK, FALSE otherwise | |
56 | ||
57 | IRQL = DISPATCH_LEVEL | |
58 | ||
59 | ========================================================================== | |
60 | */ | |
62eb734b | 61 | BOOLEAN MlmeAddBAReqSanity(struct rt_rtmp_adapter *pAd, |
51126deb | 62 | void * Msg, unsigned long MsgLen, u8 *pAddr2) |
91980990 | 63 | { |
62eb734b | 64 | struct rt_mlme_addba_req *pInfo; |
91980990 | 65 | |
62eb734b | 66 | pInfo = (struct rt_mlme_addba_req *)Msg; |
91980990 | 67 | |
62eb734b | 68 | if ((MsgLen != sizeof(struct rt_mlme_addba_req))) { |
96b3c83d | 69 | DBGPRINT(RT_DEBUG_TRACE, |
25985edc | 70 | ("MlmeAddBAReqSanity fail - message length not correct.\n")); |
96b3c83d BZ |
71 | return FALSE; |
72 | } | |
91980990 | 73 | |
96b3c83d BZ |
74 | if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) { |
75 | DBGPRINT(RT_DEBUG_TRACE, | |
76 | ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); | |
77 | return FALSE; | |
78 | } | |
91980990 | 79 | |
96b3c83d BZ |
80 | if ((pInfo->pAddr[0] & 0x01) == 0x01) { |
81 | DBGPRINT(RT_DEBUG_TRACE, | |
82 | ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); | |
83 | return FALSE; | |
84 | } | |
91980990 | 85 | |
96b3c83d | 86 | return TRUE; |
91980990 GKH |
87 | } |
88 | ||
89 | /* | |
90 | ========================================================================== | |
91 | Description: | |
92 | MLME message sanity check | |
93 | Return: | |
94 | TRUE if all parameters are OK, FALSE otherwise | |
95 | ||
96 | IRQL = DISPATCH_LEVEL | |
97 | ||
98 | ========================================================================== | |
99 | */ | |
62eb734b | 100 | BOOLEAN MlmeDelBAReqSanity(struct rt_rtmp_adapter *pAd, void * Msg, unsigned long MsgLen) |
91980990 | 101 | { |
62eb734b BZ |
102 | struct rt_mlme_delba_req *pInfo; |
103 | pInfo = (struct rt_mlme_delba_req *)Msg; | |
96b3c83d | 104 | |
62eb734b | 105 | if ((MsgLen != sizeof(struct rt_mlme_delba_req))) { |
96b3c83d | 106 | DBGPRINT(RT_DEBUG_ERROR, |
25985edc | 107 | ("MlmeDelBAReqSanity fail - message length not correct.\n")); |
96b3c83d BZ |
108 | return FALSE; |
109 | } | |
110 | ||
111 | if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) { | |
112 | DBGPRINT(RT_DEBUG_ERROR, | |
113 | ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); | |
114 | return FALSE; | |
115 | } | |
116 | ||
117 | if ((pInfo->TID & 0xf0)) { | |
118 | DBGPRINT(RT_DEBUG_ERROR, | |
119 | ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); | |
120 | return FALSE; | |
121 | } | |
122 | ||
123 | if (NdisEqualMemory | |
124 | (pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, | |
125 | MAC_ADDR_LEN) == 0) { | |
126 | DBGPRINT(RT_DEBUG_ERROR, | |
127 | ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); | |
128 | return FALSE; | |
129 | } | |
130 | ||
131 | return TRUE; | |
91980990 GKH |
132 | } |
133 | ||
62eb734b | 134 | BOOLEAN PeerAddBAReqActionSanity(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
135 | void * pMsg, |
136 | unsigned long MsgLen, u8 *pAddr2) | |
91980990 | 137 | { |
62eb734b BZ |
138 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) pMsg; |
139 | struct rt_frame_addba_req * pAddFrame; | |
140 | pAddFrame = (struct rt_frame_addba_req *) (pMsg); | |
141 | if (MsgLen < (sizeof(struct rt_frame_addba_req))) { | |
96b3c83d BZ |
142 | DBGPRINT(RT_DEBUG_ERROR, |
143 | ("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", | |
144 | MsgLen)); | |
91980990 GKH |
145 | return FALSE; |
146 | } | |
ec278fa2 | 147 | /* we support immediate BA. */ |
51126deb BZ |
148 | *(u16 *) (&pAddFrame->BaParm) = |
149 | cpu2le16(*(u16 *) (&pAddFrame->BaParm)); | |
91980990 GKH |
150 | pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); |
151 | pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word); | |
152 | ||
96b3c83d BZ |
153 | if (pAddFrame->BaParm.BAPolicy != IMMED_BA) { |
154 | DBGPRINT(RT_DEBUG_ERROR, | |
155 | ("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", | |
156 | pAddFrame->BaParm.BAPolicy)); | |
157 | DBGPRINT(RT_DEBUG_ERROR, | |
158 | ("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", | |
159 | pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, | |
160 | pAddFrame->BaParm.AMSDUSupported)); | |
91980990 GKH |
161 | return FALSE; |
162 | } | |
ec278fa2 | 163 | /* we support immediate BA. */ |
96b3c83d BZ |
164 | if (pAddFrame->BaParm.TID & 0xfff0) { |
165 | DBGPRINT(RT_DEBUG_ERROR, | |
166 | ("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", | |
167 | pAddFrame->BaParm.TID)); | |
91980990 GKH |
168 | return FALSE; |
169 | } | |
170 | COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); | |
171 | return TRUE; | |
172 | } | |
173 | ||
62eb734b | 174 | BOOLEAN PeerAddBARspActionSanity(struct rt_rtmp_adapter *pAd, |
51126deb | 175 | void * pMsg, unsigned long MsgLen) |
91980990 | 176 | { |
62eb734b | 177 | struct rt_frame_addba_rsp * pAddFrame; |
91980990 | 178 | |
62eb734b BZ |
179 | pAddFrame = (struct rt_frame_addba_rsp *) (pMsg); |
180 | if (MsgLen < (sizeof(struct rt_frame_addba_rsp))) { | |
96b3c83d BZ |
181 | DBGPRINT(RT_DEBUG_ERROR, |
182 | ("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", | |
183 | MsgLen)); | |
91980990 GKH |
184 | return FALSE; |
185 | } | |
ec278fa2 | 186 | /* we support immediate BA. */ |
51126deb BZ |
187 | *(u16 *) (&pAddFrame->BaParm) = |
188 | cpu2le16(*(u16 *) (&pAddFrame->BaParm)); | |
91980990 GKH |
189 | pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode); |
190 | pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); | |
191 | ||
96b3c83d BZ |
192 | if (pAddFrame->BaParm.BAPolicy != IMMED_BA) { |
193 | DBGPRINT(RT_DEBUG_ERROR, | |
194 | ("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", | |
195 | pAddFrame->BaParm.BAPolicy)); | |
91980990 GKH |
196 | return FALSE; |
197 | } | |
ec278fa2 | 198 | /* we support immediate BA. */ |
96b3c83d BZ |
199 | if (pAddFrame->BaParm.TID & 0xfff0) { |
200 | DBGPRINT(RT_DEBUG_ERROR, | |
201 | ("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", | |
202 | pAddFrame->BaParm.TID)); | |
91980990 GKH |
203 | return FALSE; |
204 | } | |
205 | return TRUE; | |
206 | ||
207 | } | |
208 | ||
62eb734b | 209 | BOOLEAN PeerDelBAActionSanity(struct rt_rtmp_adapter *pAd, |
51126deb | 210 | u8 Wcid, void * pMsg, unsigned long MsgLen) |
91980990 | 211 | { |
62eb734b BZ |
212 | /*struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *)pMsg; */ |
213 | struct rt_frame_delba_req * pDelFrame; | |
214 | if (MsgLen != (sizeof(struct rt_frame_delba_req))) | |
91980990 GKH |
215 | return FALSE; |
216 | ||
217 | if (Wcid >= MAX_LEN_OF_MAC_TABLE) | |
218 | return FALSE; | |
219 | ||
62eb734b | 220 | pDelFrame = (struct rt_frame_delba_req *) (pMsg); |
91980990 | 221 | |
51126deb BZ |
222 | *(u16 *) (&pDelFrame->DelbaParm) = |
223 | cpu2le16(*(u16 *) (&pDelFrame->DelbaParm)); | |
91980990 GKH |
224 | pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); |
225 | ||
96b3c83d | 226 | if (pDelFrame->DelbaParm.TID & 0xfff0) |
91980990 GKH |
227 | return FALSE; |
228 | ||
229 | return TRUE; | |
230 | } | |
231 | ||
232 | /* | |
233 | ========================================================================== | |
234 | Description: | |
235 | MLME message sanity check | |
236 | Return: | |
237 | TRUE if all parameters are OK, FALSE otherwise | |
238 | ||
239 | IRQL = DISPATCH_LEVEL | |
240 | ||
241 | ========================================================================== | |
242 | */ | |
62eb734b | 243 | BOOLEAN PeerBeaconAndProbeRspSanity(struct rt_rtmp_adapter *pAd, void * Msg, unsigned long MsgLen, u8 MsgChannel, u8 *pAddr2, u8 *pBssid, char Ssid[], u8 * pSsidLen, u8 * pBssType, u16 * pBeaconPeriod, u8 * pChannel, u8 * pNewChannel, OUT LARGE_INTEGER * pTimestamp, struct rt_cf_parm * pCfParm, u16 * pAtimWin, u16 * pCapabilityInfo, u8 * pErp, u8 * pDtimCount, u8 * pDtimPeriod, u8 * pBcastFlag, u8 * pMessageToMe, u8 SupRate[], u8 * pSupRateLen, u8 ExtRate[], u8 * pExtRateLen, u8 * pCkipFlag, u8 * pAironetCellPowerLimit, struct rt_edca_parm *pEdcaParm, struct rt_qbss_load_parm *pQbssLoad, struct rt_qos_capability_parm *pQosCapability, unsigned long * pRalinkIe, u8 * pHtCapabilityLen, u8 * pPreNHtCapabilityLen, struct rt_ht_capability_ie * pHtCapability, u8 * AddHtInfoLen, struct rt_add_ht_info_ie * AddHtInfo, u8 * NewExtChannelOffset, /* Ht extension channel offset(above or below) */ |
51126deb | 244 | u16 * LengthVIE, |
62eb734b | 245 | struct rt_ndis_802_11_variable_ies *pVIE) |
91980990 | 246 | { |
51126deb BZ |
247 | u8 *Ptr; |
248 | u8 TimLen; | |
62eb734b BZ |
249 | struct rt_frame_802_11 * pFrame; |
250 | struct rt_eid * pEid; | |
51126deb BZ |
251 | u8 SubType; |
252 | u8 Sanity; | |
253 | /*u8 ECWMin, ECWMax; */ | |
ec278fa2 | 254 | /*MAC_CSR9_STRUC Csr9; */ |
51126deb | 255 | unsigned long Length = 0; |
91980990 | 256 | |
ec278fa2 BZ |
257 | /* For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel */ |
258 | /* 1. If the AP is 11n enabled, then check the control channel. */ | |
06aea994 | 259 | /* 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!) */ |
51126deb | 260 | u8 CtrlChannel = 0; |
96b3c83d | 261 | |
ec278fa2 | 262 | /* Add for 3 necessary EID field check */ |
96b3c83d BZ |
263 | Sanity = 0; |
264 | ||
265 | *pAtimWin = 0; | |
266 | *pErp = 0; | |
267 | *pDtimCount = 0; | |
268 | *pDtimPeriod = 0; | |
269 | *pBcastFlag = 0; | |
270 | *pMessageToMe = 0; | |
271 | *pExtRateLen = 0; | |
ec278fa2 BZ |
272 | *pCkipFlag = 0; /* Default of CkipFlag is 0 */ |
273 | *pAironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF */ | |
274 | *LengthVIE = 0; /* Set the length of VIE to init value 0 */ | |
275 | *pHtCapabilityLen = 0; /* Set the length of VIE to init value 0 */ | |
91980990 | 276 | if (pAd->OpMode == OPMODE_STA) |
ec278fa2 BZ |
277 | *pPreNHtCapabilityLen = 0; /* Set the length of VIE to init value 0 */ |
278 | *AddHtInfoLen = 0; /* Set the length of VIE to init value 0 */ | |
96b3c83d BZ |
279 | *pRalinkIe = 0; |
280 | *pNewChannel = 0; | |
ec278fa2 BZ |
281 | *NewExtChannelOffset = 0xff; /*Default 0xff means no such IE */ |
282 | pCfParm->bValid = FALSE; /* default: no IE_CF found */ | |
283 | pQbssLoad->bValid = FALSE; /* default: no IE_QBSS_LOAD found */ | |
284 | pEdcaParm->bValid = FALSE; /* default: no IE_EDCA_PARAMETER found */ | |
285 | pQosCapability->bValid = FALSE; /* default: no IE_QOS_CAPABILITY found */ | |
96b3c83d | 286 | |
62eb734b | 287 | pFrame = (struct rt_frame_802_11 *) Msg; |
96b3c83d | 288 | |
ec278fa2 | 289 | /* get subtype from header */ |
51126deb | 290 | SubType = (u8)pFrame->Hdr.FC.SubType; |
96b3c83d | 291 | |
ec278fa2 | 292 | /* get Addr2 and BSSID from header */ |
96b3c83d BZ |
293 | COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); |
294 | COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); | |
91980990 | 295 | |
96b3c83d BZ |
296 | Ptr = pFrame->Octet; |
297 | Length += LENGTH_802_11; | |
91980990 | 298 | |
ec278fa2 | 299 | /* get timestamp from payload and advance the pointer */ |
96b3c83d | 300 | NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); |
91980990 | 301 | |
96b3c83d BZ |
302 | pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); |
303 | pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); | |
91980990 | 304 | |
96b3c83d BZ |
305 | Ptr += TIMESTAMP_LEN; |
306 | Length += TIMESTAMP_LEN; | |
91980990 | 307 | |
ec278fa2 | 308 | /* get beacon interval from payload and advance the pointer */ |
96b3c83d BZ |
309 | NdisMoveMemory(pBeaconPeriod, Ptr, 2); |
310 | Ptr += 2; | |
311 | Length += 2; | |
91980990 | 312 | |
ec278fa2 | 313 | /* get capability info from payload and advance the pointer */ |
96b3c83d BZ |
314 | NdisMoveMemory(pCapabilityInfo, Ptr, 2); |
315 | Ptr += 2; | |
316 | Length += 2; | |
91980990 | 317 | |
96b3c83d BZ |
318 | if (CAP_IS_ESS_ON(*pCapabilityInfo)) |
319 | *pBssType = BSS_INFRA; | |
320 | else | |
321 | *pBssType = BSS_ADHOC; | |
322 | ||
62eb734b | 323 | pEid = (struct rt_eid *) Ptr; |
96b3c83d | 324 | |
ec278fa2 | 325 | /* get variable fields from payload and advance the pointer */ |
96b3c83d | 326 | while ((Length + 2 + pEid->Len) <= MsgLen) { |
ec278fa2 BZ |
327 | /* */ |
328 | /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow. */ | |
329 | /* */ | |
96b3c83d BZ |
330 | if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) { |
331 | DBGPRINT(RT_DEBUG_WARN, | |
332 | ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", | |
333 | (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); | |
334 | break; | |
335 | } | |
336 | ||
337 | switch (pEid->Eid) { | |
338 | case IE_SSID: | |
ec278fa2 | 339 | /* Already has one SSID EID in this beacon, ignore the second one */ |
96b3c83d BZ |
340 | if (Sanity & 0x1) |
341 | break; | |
342 | if (pEid->Len <= MAX_LEN_OF_SSID) { | |
343 | NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); | |
344 | *pSsidLen = pEid->Len; | |
345 | Sanity |= 0x1; | |
346 | } else { | |
347 | DBGPRINT(RT_DEBUG_TRACE, | |
348 | ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n", | |
349 | pEid->Len)); | |
350 | return FALSE; | |
351 | } | |
352 | break; | |
353 | ||
354 | case IE_SUPP_RATES: | |
355 | if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { | |
356 | Sanity |= 0x2; | |
357 | NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); | |
358 | *pSupRateLen = pEid->Len; | |
359 | ||
ec278fa2 BZ |
360 | /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates */ |
361 | /* from ScanTab. We should report as is. And filter out unsupported */ | |
362 | /* rates in MlmeAux. */ | |
363 | /* Check against the supported rates */ | |
364 | /* RTMPCheckRates(pAd, SupRate, pSupRateLen); */ | |
96b3c83d BZ |
365 | } else { |
366 | DBGPRINT(RT_DEBUG_TRACE, | |
367 | ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n", | |
368 | pEid->Len)); | |
369 | return FALSE; | |
370 | } | |
371 | break; | |
372 | ||
373 | case IE_HT_CAP: | |
06aea994 | 374 | if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension! */ |
91980990 | 375 | { |
96b3c83d | 376 | NdisMoveMemory(pHtCapability, pEid->Octet, |
62eb734b | 377 | sizeof(struct rt_ht_capability_ie)); |
ec278fa2 | 378 | *pHtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes. */ |
91980990 | 379 | |
51126deb BZ |
380 | *(u16 *) (&pHtCapability->HtCapInfo) = |
381 | cpu2le16(*(u16 *) | |
96b3c83d | 382 | (&pHtCapability->HtCapInfo)); |
51126deb BZ |
383 | *(u16 *) (&pHtCapability->ExtHtCapInfo) = |
384 | cpu2le16(*(u16 *) | |
96b3c83d | 385 | (&pHtCapability->ExtHtCapInfo)); |
91980990 | 386 | |
91980990 | 387 | { |
ec278fa2 | 388 | *pPreNHtCapabilityLen = 0; /* Nnow we only support 26 bytes. */ |
91980990 | 389 | |
51126deb | 390 | Ptr = (u8 *)pVIE; |
96b3c83d BZ |
391 | NdisMoveMemory(Ptr + *LengthVIE, |
392 | &pEid->Eid, | |
393 | pEid->Len + 2); | |
91980990 GKH |
394 | *LengthVIE += (pEid->Len + 2); |
395 | } | |
96b3c83d BZ |
396 | } else { |
397 | DBGPRINT(RT_DEBUG_WARN, | |
398 | ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", | |
399 | pEid->Len)); | |
91980990 GKH |
400 | } |
401 | ||
96b3c83d BZ |
402 | break; |
403 | case IE_ADD_HT: | |
62eb734b | 404 | if (pEid->Len >= sizeof(struct rt_add_ht_info_ie)) { |
ec278fa2 | 405 | /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */ |
62eb734b | 406 | /* copy first sizeof(struct rt_add_ht_info_ie) */ |
96b3c83d | 407 | NdisMoveMemory(AddHtInfo, pEid->Octet, |
62eb734b | 408 | sizeof(struct rt_add_ht_info_ie)); |
91980990 GKH |
409 | *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; |
410 | ||
411 | CtrlChannel = AddHtInfo->ControlChan; | |
412 | ||
51126deb BZ |
413 | *(u16 *) (&AddHtInfo->AddHtInfo2) = |
414 | cpu2le16(*(u16 *) | |
96b3c83d | 415 | (&AddHtInfo->AddHtInfo2)); |
51126deb BZ |
416 | *(u16 *) (&AddHtInfo->AddHtInfo3) = |
417 | cpu2le16(*(u16 *) | |
96b3c83d | 418 | (&AddHtInfo->AddHtInfo3)); |
91980990 | 419 | |
91980990 | 420 | { |
51126deb | 421 | Ptr = (u8 *)pVIE; |
96b3c83d BZ |
422 | NdisMoveMemory(Ptr + *LengthVIE, |
423 | &pEid->Eid, | |
424 | pEid->Len + 2); | |
425 | *LengthVIE += (pEid->Len + 2); | |
91980990 | 426 | } |
96b3c83d BZ |
427 | } else { |
428 | DBGPRINT(RT_DEBUG_WARN, | |
429 | ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); | |
91980990 GKH |
430 | } |
431 | ||
96b3c83d BZ |
432 | break; |
433 | case IE_SECONDARY_CH_OFFSET: | |
434 | if (pEid->Len == 1) { | |
91980990 | 435 | *NewExtChannelOffset = pEid->Octet[0]; |
96b3c83d BZ |
436 | } else { |
437 | DBGPRINT(RT_DEBUG_WARN, | |
438 | ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); | |
91980990 GKH |
439 | } |
440 | ||
96b3c83d BZ |
441 | break; |
442 | case IE_FH_PARM: | |
443 | DBGPRINT(RT_DEBUG_TRACE, | |
444 | ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); | |
445 | break; | |
91980990 | 446 | |
96b3c83d BZ |
447 | case IE_DS_PARM: |
448 | if (pEid->Len == 1) { | |
449 | *pChannel = *pEid->Octet; | |
6a28a69a | 450 | |
96b3c83d BZ |
451 | { |
452 | if (ChannelSanity(pAd, *pChannel) == 0) { | |
91980990 | 453 | |
96b3c83d | 454 | return FALSE; |
91980990 | 455 | } |
ca97b838 | 456 | } |
96b3c83d BZ |
457 | |
458 | Sanity |= 0x4; | |
459 | } else { | |
460 | DBGPRINT(RT_DEBUG_TRACE, | |
461 | ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n", | |
462 | pEid->Len)); | |
463 | return FALSE; | |
ca97b838 | 464 | } |
96b3c83d BZ |
465 | break; |
466 | ||
467 | case IE_CF_PARM: | |
468 | if (pEid->Len == 6) { | |
469 | pCfParm->bValid = TRUE; | |
470 | pCfParm->CfpCount = pEid->Octet[0]; | |
471 | pCfParm->CfpPeriod = pEid->Octet[1]; | |
472 | pCfParm->CfpMaxDuration = | |
473 | pEid->Octet[2] + 256 * pEid->Octet[3]; | |
474 | pCfParm->CfpDurRemaining = | |
475 | pEid->Octet[4] + 256 * pEid->Octet[5]; | |
476 | } else { | |
477 | DBGPRINT(RT_DEBUG_TRACE, | |
478 | ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); | |
479 | return FALSE; | |
480 | } | |
481 | break; | |
482 | ||
483 | case IE_IBSS_PARM: | |
484 | if (pEid->Len == 2) { | |
485 | NdisMoveMemory(pAtimWin, pEid->Octet, | |
486 | pEid->Len); | |
487 | } else { | |
488 | DBGPRINT(RT_DEBUG_TRACE, | |
489 | ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); | |
490 | return FALSE; | |
491 | } | |
492 | break; | |
493 | ||
494 | case IE_TIM: | |
495 | if (INFRA_ON(pAd) && SubType == SUBTYPE_BEACON) { | |
51126deb | 496 | GetTimBit((char *)pEid, pAd->StaActive.Aid, |
96b3c83d BZ |
497 | &TimLen, pBcastFlag, pDtimCount, |
498 | pDtimPeriod, pMessageToMe); | |
499 | } | |
500 | break; | |
501 | case IE_CHANNEL_SWITCH_ANNOUNCEMENT: | |
502 | if (pEid->Len == 3) { | |
ec278fa2 | 503 | *pNewChannel = pEid->Octet[1]; /*extract new channel number */ |
96b3c83d BZ |
504 | } |
505 | break; | |
506 | ||
ec278fa2 BZ |
507 | /* New for WPA */ |
508 | /* CCX v2 has the same IE, we need to parse that too */ | |
509 | /* Wifi WMM use the same IE vale, need to parse that too */ | |
510 | /* case IE_WPA: */ | |
96b3c83d | 511 | case IE_VENDOR_SPECIFIC: |
ec278fa2 BZ |
512 | /* Check Broadcom/Atheros 802.11n OUI version, for HT Capability IE. */ |
513 | /* This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. */ | |
96b3c83d BZ |
514 | /*if (NdisEqualMemory(pEid->Octet, BROADCOM_OUI, 3) && (pEid->Len >= 4)) |
515 | { | |
516 | if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 30)) | |
517 | { | |
518 | { | |
62eb734b | 519 | NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(struct rt_ht_capability_ie)); |
96b3c83d BZ |
520 | *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. |
521 | } | |
522 | } | |
523 | if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 26)) | |
524 | { | |
525 | { | |
62eb734b | 526 | NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(struct rt_add_ht_info_ie)); |
96b3c83d BZ |
527 | *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; // Nnow we only support 26 bytes. |
528 | } | |
529 | } | |
530 | } | |
531 | */ | |
ec278fa2 | 532 | /* Check the OUI version, filter out non-standard usage */ |
96b3c83d BZ |
533 | if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) |
534 | && (pEid->Len == 7)) { | |
ec278fa2 | 535 | /**pRalinkIe = pEid->Octet[3]; */ |
96b3c83d BZ |
536 | if (pEid->Octet[3] != 0) |
537 | *pRalinkIe = pEid->Octet[3]; | |
538 | else | |
ec278fa2 | 539 | *pRalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. */ |
96b3c83d | 540 | } |
ec278fa2 | 541 | /* This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. */ |
96b3c83d | 542 | |
ec278fa2 BZ |
543 | /* Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP, */ |
544 | /* Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE */ | |
96b3c83d BZ |
545 | else if ((*pHtCapabilityLen == 0) |
546 | && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, | |
547 | 3) && (pEid->Len >= 4) | |
548 | && (pAd->OpMode == OPMODE_STA)) { | |
549 | if ((pEid->Octet[3] == OUI_PREN_HT_CAP) | |
550 | && (pEid->Len >= 30) | |
551 | && (*pHtCapabilityLen == 0)) { | |
552 | NdisMoveMemory(pHtCapability, | |
553 | &pEid->Octet[4], | |
554 | sizeof | |
62eb734b | 555 | (struct rt_ht_capability_ie)); |
96b3c83d BZ |
556 | *pPreNHtCapabilityLen = SIZE_HT_CAP_IE; |
557 | } | |
558 | ||
559 | if ((pEid->Octet[3] == OUI_PREN_ADD_HT) | |
560 | && (pEid->Len >= 26)) { | |
561 | NdisMoveMemory(AddHtInfo, | |
562 | &pEid->Octet[4], | |
62eb734b | 563 | sizeof(struct rt_add_ht_info_ie)); |
96b3c83d BZ |
564 | *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; |
565 | } | |
566 | } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) { | |
ec278fa2 | 567 | /* Copy to pVIE which will report to microsoft bssid list. */ |
51126deb | 568 | Ptr = (u8 *)pVIE; |
96b3c83d BZ |
569 | NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, |
570 | pEid->Len + 2); | |
571 | *LengthVIE += (pEid->Len + 2); | |
572 | } else | |
573 | if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) | |
574 | && (pEid->Len == 24)) { | |
51126deb | 575 | u8 *ptr; |
96b3c83d BZ |
576 | int i; |
577 | ||
ec278fa2 | 578 | /* parsing EDCA parameters */ |
96b3c83d | 579 | pEdcaParm->bValid = TRUE; |
ec278fa2 BZ |
580 | pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ |
581 | pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ | |
582 | pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ | |
96b3c83d BZ |
583 | pEdcaParm->EdcaUpdateCount = |
584 | pEid->Octet[6] & 0x0f; | |
585 | pEdcaParm->bAPSDCapable = | |
586 | (pEid->Octet[6] & 0x80) ? 1 : 0; | |
587 | ptr = &pEid->Octet[8]; | |
588 | for (i = 0; i < 4; i++) { | |
51126deb | 589 | u8 aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ |
ec278fa2 BZ |
590 | pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ |
591 | pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ | |
592 | pEdcaParm->Cwmin[aci] = *(ptr + 1) & 0x0f; /* b0~4 is Cwmin */ | |
593 | pEdcaParm->Cwmax[aci] = *(ptr + 1) >> 4; /* b5~8 is Cwmax */ | |
594 | pEdcaParm->Txop[aci] = *(ptr + 2) + 256 * (*(ptr + 3)); /* in unit of 32-us */ | |
595 | ptr += 4; /* point to next AC */ | |
ca97b838 | 596 | } |
96b3c83d BZ |
597 | } else |
598 | if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) | |
599 | && (pEid->Len == 7)) { | |
ec278fa2 | 600 | /* parsing EDCA parameters */ |
96b3c83d | 601 | pEdcaParm->bValid = TRUE; |
ec278fa2 BZ |
602 | pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ |
603 | pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ | |
604 | pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ | |
96b3c83d BZ |
605 | pEdcaParm->EdcaUpdateCount = |
606 | pEid->Octet[6] & 0x0f; | |
607 | pEdcaParm->bAPSDCapable = | |
608 | (pEid->Octet[6] & 0x80) ? 1 : 0; | |
609 | ||
ec278fa2 | 610 | /* use default EDCA parameter */ |
96b3c83d BZ |
611 | pEdcaParm->bACM[QID_AC_BE] = 0; |
612 | pEdcaParm->Aifsn[QID_AC_BE] = 3; | |
613 | pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS; | |
614 | pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; | |
615 | pEdcaParm->Txop[QID_AC_BE] = 0; | |
616 | ||
617 | pEdcaParm->bACM[QID_AC_BK] = 0; | |
618 | pEdcaParm->Aifsn[QID_AC_BK] = 7; | |
619 | pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; | |
620 | pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; | |
621 | pEdcaParm->Txop[QID_AC_BK] = 0; | |
622 | ||
623 | pEdcaParm->bACM[QID_AC_VI] = 0; | |
624 | pEdcaParm->Aifsn[QID_AC_VI] = 2; | |
625 | pEdcaParm->Cwmin[QID_AC_VI] = | |
626 | CW_MIN_IN_BITS - 1; | |
627 | pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; | |
ec278fa2 | 628 | pEdcaParm->Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms */ |
96b3c83d BZ |
629 | |
630 | pEdcaParm->bACM[QID_AC_VO] = 0; | |
631 | pEdcaParm->Aifsn[QID_AC_VO] = 2; | |
632 | pEdcaParm->Cwmin[QID_AC_VO] = | |
633 | CW_MIN_IN_BITS - 2; | |
634 | pEdcaParm->Cwmax[QID_AC_VO] = | |
635 | CW_MAX_IN_BITS - 1; | |
ec278fa2 | 636 | pEdcaParm->Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms */ |
96b3c83d BZ |
637 | } |
638 | ||
639 | break; | |
640 | ||
641 | case IE_EXT_SUPP_RATES: | |
642 | if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { | |
643 | NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); | |
644 | *pExtRateLen = pEid->Len; | |
645 | ||
ec278fa2 BZ |
646 | /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates */ |
647 | /* from ScanTab. We should report as is. And filter out unsupported */ | |
648 | /* rates in MlmeAux. */ | |
649 | /* Check against the supported rates */ | |
650 | /* RTMPCheckRates(pAd, ExtRate, pExtRateLen); */ | |
ca97b838 | 651 | } |
96b3c83d BZ |
652 | break; |
653 | ||
654 | case IE_ERP: | |
655 | if (pEid->Len == 1) { | |
51126deb | 656 | *pErp = (u8)pEid->Octet[0]; |
96b3c83d BZ |
657 | } |
658 | break; | |
659 | ||
660 | case IE_AIRONET_CKIP: | |
ec278fa2 BZ |
661 | /* 0. Check Aironet IE length, it must be larger or equal to 28 */ |
662 | /* Cisco AP350 used length as 28 */ | |
663 | /* Cisco AP12XX used length as 30 */ | |
96b3c83d BZ |
664 | if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) |
665 | break; | |
666 | ||
ec278fa2 | 667 | /* 1. Copy CKIP flag byte to buffer for process */ |
96b3c83d BZ |
668 | *pCkipFlag = *(pEid->Octet + 8); |
669 | break; | |
670 | ||
671 | case IE_AP_TX_POWER: | |
ec278fa2 BZ |
672 | /* AP Control of Client Transmit Power */ |
673 | /*0. Check Aironet IE length, it must be 6 */ | |
96b3c83d BZ |
674 | if (pEid->Len != 0x06) |
675 | break; | |
676 | ||
ec278fa2 | 677 | /* Get cell power limit in dBm */ |
96b3c83d BZ |
678 | if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) |
679 | *pAironetCellPowerLimit = *(pEid->Octet + 4); | |
680 | break; | |
681 | ||
ec278fa2 | 682 | /* WPA2 & 802.11i RSN */ |
96b3c83d | 683 | case IE_RSN: |
ec278fa2 | 684 | /* There is no OUI for version anymore, check the group cipher OUI before copying */ |
96b3c83d | 685 | if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) { |
ec278fa2 | 686 | /* Copy to pVIE which will report to microsoft bssid list. */ |
51126deb | 687 | Ptr = (u8 *)pVIE; |
96b3c83d BZ |
688 | NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, |
689 | pEid->Len + 2); | |
690 | *LengthVIE += (pEid->Len + 2); | |
691 | } | |
692 | break; | |
693 | ||
694 | default: | |
695 | break; | |
696 | } | |
697 | ||
ec278fa2 | 698 | Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ |
62eb734b | 699 | pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len); |
96b3c83d BZ |
700 | } |
701 | ||
ec278fa2 | 702 | /* For some 11a AP. it did not have the channel EID, patch here */ |
91980990 | 703 | { |
51126deb | 704 | u8 LatchRfChannel = MsgChannel; |
96b3c83d | 705 | if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) { |
91980990 GKH |
706 | if (CtrlChannel != 0) |
707 | *pChannel = CtrlChannel; | |
708 | else | |
709 | *pChannel = LatchRfChannel; | |
710 | Sanity |= 0x4; | |
711 | } | |
712 | } | |
91980990 | 713 | |
96b3c83d BZ |
714 | if (Sanity != 0x7) { |
715 | DBGPRINT(RT_DEBUG_LOUD, | |
716 | ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", | |
717 | Sanity)); | |
91980990 | 718 | return FALSE; |
96b3c83d | 719 | } else { |
91980990 GKH |
720 | return TRUE; |
721 | } | |
722 | ||
723 | } | |
724 | ||
91980990 GKH |
725 | /* |
726 | ========================================================================== | |
727 | Description: | |
728 | MLME message sanity check | |
729 | Return: | |
730 | TRUE if all parameters are OK, FALSE otherwise | |
731 | ========================================================================== | |
732 | */ | |
62eb734b | 733 | BOOLEAN MlmeScanReqSanity(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
734 | void * Msg, |
735 | unsigned long MsgLen, | |
736 | u8 * pBssType, | |
737 | char Ssid[], | |
738 | u8 * pSsidLen, u8 * pScanType) | |
91980990 | 739 | { |
62eb734b | 740 | struct rt_mlme_scan_req *Info; |
91980990 | 741 | |
62eb734b | 742 | Info = (struct rt_mlme_scan_req *)(Msg); |
91980990 GKH |
743 | *pBssType = Info->BssType; |
744 | *pSsidLen = Info->SsidLen; | |
745 | NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); | |
746 | *pScanType = Info->ScanType; | |
747 | ||
96b3c83d BZ |
748 | if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC |
749 | || *pBssType == BSS_ANY) | |
750 | && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE)) { | |
91980990 | 751 | return TRUE; |
96b3c83d BZ |
752 | } else { |
753 | DBGPRINT(RT_DEBUG_TRACE, | |
754 | ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); | |
91980990 GKH |
755 | return FALSE; |
756 | } | |
757 | } | |
758 | ||
ec278fa2 | 759 | /* IRQL = DISPATCH_LEVEL */ |
62eb734b | 760 | u8 ChannelSanity(struct rt_rtmp_adapter *pAd, u8 channel) |
91980990 | 761 | { |
96b3c83d BZ |
762 | int i; |
763 | ||
764 | for (i = 0; i < pAd->ChannelListNum; i++) { | |
765 | if (channel == pAd->ChannelList[i].Channel) | |
766 | return 1; | |
767 | } | |
768 | return 0; | |
91980990 GKH |
769 | } |
770 | ||
771 | /* | |
772 | ========================================================================== | |
773 | Description: | |
774 | MLME message sanity check | |
775 | Return: | |
776 | TRUE if all parameters are OK, FALSE otherwise | |
777 | ||
778 | IRQL = DISPATCH_LEVEL | |
779 | ||
780 | ========================================================================== | |
781 | */ | |
62eb734b | 782 | BOOLEAN PeerDeauthSanity(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
783 | void * Msg, |
784 | unsigned long MsgLen, | |
785 | u8 *pAddr2, u16 * pReason) | |
91980990 | 786 | { |
62eb734b | 787 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; |
91980990 | 788 | |
96b3c83d BZ |
789 | COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); |
790 | NdisMoveMemory(pReason, &pFrame->Octet[0], 2); | |
91980990 | 791 | |
96b3c83d | 792 | return TRUE; |
91980990 GKH |
793 | } |
794 | ||
795 | /* | |
796 | ========================================================================== | |
797 | Description: | |
798 | MLME message sanity check | |
799 | Return: | |
800 | TRUE if all parameters are OK, FALSE otherwise | |
801 | ||
802 | IRQL = DISPATCH_LEVEL | |
803 | ||
804 | ========================================================================== | |
805 | */ | |
62eb734b | 806 | BOOLEAN PeerAuthSanity(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
807 | void * Msg, |
808 | unsigned long MsgLen, | |
809 | u8 *pAddr, | |
810 | u16 * pAlg, | |
811 | u16 * pSeq, | |
812 | u16 * pStatus, char * pChlgText) | |
91980990 | 813 | { |
62eb734b | 814 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; |
96b3c83d BZ |
815 | |
816 | COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); | |
817 | NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); | |
818 | NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); | |
819 | NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); | |
820 | ||
821 | if (*pAlg == AUTH_MODE_OPEN) { | |
822 | if (*pSeq == 1 || *pSeq == 2) { | |
823 | return TRUE; | |
824 | } else { | |
825 | DBGPRINT(RT_DEBUG_TRACE, | |
826 | ("PeerAuthSanity fail - wrong Seg#\n")); | |
827 | return FALSE; | |
828 | } | |
829 | } else if (*pAlg == AUTH_MODE_KEY) { | |
830 | if (*pSeq == 1 || *pSeq == 4) { | |
831 | return TRUE; | |
832 | } else if (*pSeq == 2 || *pSeq == 3) { | |
833 | NdisMoveMemory(pChlgText, &pFrame->Octet[8], | |
834 | CIPHER_TEXT_LEN); | |
835 | return TRUE; | |
836 | } else { | |
837 | DBGPRINT(RT_DEBUG_TRACE, | |
838 | ("PeerAuthSanity fail - wrong Seg#\n")); | |
839 | return FALSE; | |
840 | } | |
841 | } else { | |
842 | DBGPRINT(RT_DEBUG_TRACE, | |
843 | ("PeerAuthSanity fail - wrong algorithm\n")); | |
844 | return FALSE; | |
845 | } | |
91980990 GKH |
846 | } |
847 | ||
848 | /* | |
849 | ========================================================================== | |
850 | Description: | |
851 | MLME message sanity check | |
852 | Return: | |
853 | TRUE if all parameters are OK, FALSE otherwise | |
854 | ========================================================================== | |
855 | */ | |
62eb734b | 856 | BOOLEAN MlmeAuthReqSanity(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
857 | void * Msg, |
858 | unsigned long MsgLen, | |
859 | u8 *pAddr, | |
860 | unsigned long * pTimeout, u16 * pAlg) | |
91980990 | 861 | { |
62eb734b | 862 | struct rt_mlme_auth_req *pInfo; |
96b3c83d | 863 | |
62eb734b | 864 | pInfo = (struct rt_mlme_auth_req *)Msg; |
96b3c83d BZ |
865 | COPY_MAC_ADDR(pAddr, pInfo->Addr); |
866 | *pTimeout = pInfo->Timeout; | |
867 | *pAlg = pInfo->Alg; | |
868 | ||
869 | if (((*pAlg == AUTH_MODE_KEY) || (*pAlg == AUTH_MODE_OPEN) | |
870 | ) && ((*pAddr & 0x01) == 0)) { | |
871 | return TRUE; | |
872 | } else { | |
873 | DBGPRINT(RT_DEBUG_TRACE, | |
874 | ("MlmeAuthReqSanity fail - wrong algorithm\n")); | |
875 | return FALSE; | |
876 | } | |
91980990 GKH |
877 | } |
878 | ||
879 | /* | |
880 | ========================================================================== | |
881 | Description: | |
882 | MLME message sanity check | |
883 | Return: | |
884 | TRUE if all parameters are OK, FALSE otherwise | |
885 | ||
886 | IRQL = DISPATCH_LEVEL | |
887 | ||
888 | ========================================================================== | |
889 | */ | |
62eb734b | 890 | BOOLEAN MlmeAssocReqSanity(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
891 | void * Msg, |
892 | unsigned long MsgLen, | |
893 | u8 *pApAddr, | |
894 | u16 * pCapabilityInfo, | |
895 | unsigned long * pTimeout, u16 * pListenIntv) | |
91980990 | 896 | { |
62eb734b | 897 | struct rt_mlme_assoc_req *pInfo; |
91980990 | 898 | |
62eb734b | 899 | pInfo = (struct rt_mlme_assoc_req *)Msg; |
ec278fa2 BZ |
900 | *pTimeout = pInfo->Timeout; /* timeout */ |
901 | COPY_MAC_ADDR(pApAddr, pInfo->Addr); /* AP address */ | |
902 | *pCapabilityInfo = pInfo->CapabilityInfo; /* capability info */ | |
96b3c83d | 903 | *pListenIntv = pInfo->ListenIntv; |
91980990 | 904 | |
96b3c83d | 905 | return TRUE; |
91980990 GKH |
906 | } |
907 | ||
908 | /* | |
909 | ========================================================================== | |
910 | Description: | |
911 | MLME message sanity check | |
912 | Return: | |
913 | TRUE if all parameters are OK, FALSE otherwise | |
914 | ||
915 | IRQL = DISPATCH_LEVEL | |
916 | ||
917 | ========================================================================== | |
918 | */ | |
62eb734b | 919 | BOOLEAN PeerDisassocSanity(struct rt_rtmp_adapter *pAd, |
51126deb BZ |
920 | void * Msg, |
921 | unsigned long MsgLen, | |
922 | u8 *pAddr2, u16 * pReason) | |
91980990 | 923 | { |
62eb734b | 924 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; |
91980990 | 925 | |
96b3c83d BZ |
926 | COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); |
927 | NdisMoveMemory(pReason, &pFrame->Octet[0], 2); | |
91980990 | 928 | |
96b3c83d | 929 | return TRUE; |
91980990 GKH |
930 | } |
931 | ||
932 | /* | |
933 | ======================================================================== | |
934 | Routine Description: | |
935 | Sanity check NetworkType (11b, 11g or 11a) | |
936 | ||
937 | Arguments: | |
938 | pBss - Pointer to BSS table. | |
939 | ||
940 | Return Value: | |
941 | Ndis802_11DS .......(11b) | |
942 | Ndis802_11OFDM24....(11g) | |
943 | Ndis802_11OFDM5.....(11a) | |
944 | ||
945 | IRQL = DISPATCH_LEVEL | |
946 | ||
947 | ======================================================================== | |
948 | */ | |
62eb734b | 949 | NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(struct rt_bss_entry *pBss) |
91980990 | 950 | { |
96b3c83d | 951 | NDIS_802_11_NETWORK_TYPE NetWorkType; |
51126deb | 952 | u8 rate, i; |
91980990 GKH |
953 | |
954 | NetWorkType = Ndis802_11DS; | |
955 | ||
96b3c83d | 956 | if (pBss->Channel <= 14) { |
ec278fa2 BZ |
957 | /* */ |
958 | /* First check support Rate. */ | |
959 | /* */ | |
96b3c83d | 960 | for (i = 0; i < pBss->SupRateLen; i++) { |
ec278fa2 | 961 | rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit */ |
96b3c83d BZ |
962 | if ((rate == 2) || (rate == 4) || (rate == 11) |
963 | || (rate == 22)) { | |
91980990 | 964 | continue; |
96b3c83d | 965 | } else { |
ec278fa2 BZ |
966 | /* */ |
967 | /* Otherwise (even rate > 108) means Ndis802_11OFDM24 */ | |
968 | /* */ | |
91980990 GKH |
969 | NetWorkType = Ndis802_11OFDM24; |
970 | break; | |
971 | } | |
972 | } | |
973 | ||
ec278fa2 BZ |
974 | /* */ |
975 | /* Second check Extend Rate. */ | |
976 | /* */ | |
96b3c83d BZ |
977 | if (NetWorkType != Ndis802_11OFDM24) { |
978 | for (i = 0; i < pBss->ExtRateLen; i++) { | |
ec278fa2 | 979 | rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit */ |
96b3c83d BZ |
980 | if ((rate == 2) || (rate == 4) || (rate == 11) |
981 | || (rate == 22)) { | |
91980990 | 982 | continue; |
96b3c83d | 983 | } else { |
ec278fa2 BZ |
984 | /* */ |
985 | /* Otherwise (even rate > 108) means Ndis802_11OFDM24 */ | |
986 | /* */ | |
91980990 GKH |
987 | NetWorkType = Ndis802_11OFDM24; |
988 | break; | |
989 | } | |
990 | } | |
991 | } | |
96b3c83d | 992 | } else { |
91980990 GKH |
993 | NetWorkType = Ndis802_11OFDM5; |
994 | } | |
995 | ||
96b3c83d BZ |
996 | if (pBss->HtCapabilityLen != 0) { |
997 | if (NetWorkType == Ndis802_11OFDM5) | |
998 | NetWorkType = Ndis802_11OFDM5_N; | |
999 | else | |
1000 | NetWorkType = Ndis802_11OFDM24_N; | |
1001 | } | |
91980990 GKH |
1002 | |
1003 | return NetWorkType; | |
1004 | } | |
ca97b838 BZ |
1005 | |
1006 | /* | |
1007 | ========================================================================== | |
1008 | Description: | |
1009 | Check the validity of the received EAPoL frame | |
1010 | Return: | |
1011 | TRUE if all parameters are OK, | |
1012 | FALSE otherwise | |
1013 | ========================================================================== | |
1014 | */ | |
62eb734b BZ |
1015 | BOOLEAN PeerWpaMessageSanity(struct rt_rtmp_adapter *pAd, |
1016 | struct rt_eapol_packet * pMsg, | |
51126deb | 1017 | unsigned long MsgLen, |
62eb734b | 1018 | u8 MsgType, struct rt_mac_table_entry *pEntry) |
ca97b838 | 1019 | { |
51126deb | 1020 | u8 mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE]; |
96b3c83d BZ |
1021 | BOOLEAN bReplayDiff = FALSE; |
1022 | BOOLEAN bWPA2 = FALSE; | |
62eb734b | 1023 | struct rt_key_info EapolKeyInfo; |
51126deb | 1024 | u8 GroupKeyIndex = 0; |
ca97b838 BZ |
1025 | |
1026 | NdisZeroMemory(mic, sizeof(mic)); | |
1027 | NdisZeroMemory(digest, sizeof(digest)); | |
1028 | NdisZeroMemory(KEYDATA, sizeof(KEYDATA)); | |
51126deb | 1029 | NdisZeroMemory((u8 *)& EapolKeyInfo, sizeof(EapolKeyInfo)); |
ca97b838 | 1030 | |
51126deb | 1031 | NdisMoveMemory((u8 *)& EapolKeyInfo, |
62eb734b | 1032 | (u8 *)& pMsg->KeyDesc.KeyInfo, sizeof(struct rt_key_info)); |
ca97b838 | 1033 | |
51126deb | 1034 | *((u16 *) & EapolKeyInfo) = cpu2le16(*((u16 *) & EapolKeyInfo)); |
ca97b838 | 1035 | |
ec278fa2 | 1036 | /* Choose WPA2 or not */ |
96b3c83d BZ |
1037 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) |
1038 | || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) | |
ca97b838 BZ |
1039 | bWPA2 = TRUE; |
1040 | ||
ec278fa2 | 1041 | /* 0. Check MsgType */ |
96b3c83d BZ |
1042 | if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1)) { |
1043 | DBGPRINT(RT_DEBUG_ERROR, | |
1044 | ("The message type is invalid(%d)! \n", MsgType)); | |
ca97b838 BZ |
1045 | return FALSE; |
1046 | } | |
ec278fa2 BZ |
1047 | /* 1. Replay counter check */ |
1048 | if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) /* For supplicant */ | |
ca97b838 | 1049 | { |
ec278fa2 BZ |
1050 | /* First validate replay counter, only accept message with larger replay counter. */ |
1051 | /* Let equal pass, some AP start with all zero replay counter */ | |
51126deb | 1052 | u8 ZeroReplay[LEN_KEY_DESC_REPLAY]; |
96b3c83d BZ |
1053 | |
1054 | NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); | |
1055 | if ((RTMPCompareMemory | |
1056 | (pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, | |
1057 | LEN_KEY_DESC_REPLAY) != 1) | |
1058 | && | |
1059 | (RTMPCompareMemory | |
1060 | (pMsg->KeyDesc.ReplayCounter, ZeroReplay, | |
1061 | LEN_KEY_DESC_REPLAY) != 0)) { | |
ca97b838 | 1062 | bReplayDiff = TRUE; |
96b3c83d | 1063 | } |
ec278fa2 | 1064 | } else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) /* For authenticator */ |
ca97b838 | 1065 | { |
ec278fa2 | 1066 | /* check Replay Counter coresponds to MSG from authenticator, otherwise discard */ |
96b3c83d BZ |
1067 | if (!NdisEqualMemory |
1068 | (pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, | |
1069 | LEN_KEY_DESC_REPLAY)) { | |
ca97b838 | 1070 | bReplayDiff = TRUE; |
96b3c83d | 1071 | } |
ca97b838 | 1072 | } |
ec278fa2 | 1073 | /* Replay Counter different condition */ |
96b3c83d | 1074 | if (bReplayDiff) { |
ec278fa2 | 1075 | /* send wireless event - for replay counter different */ |
ca97b838 | 1076 | if (pAd->CommonCfg.bWirelessEvent) |
96b3c83d BZ |
1077 | RTMPSendWirelessEvent(pAd, |
1078 | IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, | |
1079 | pEntry->Addr, pEntry->apidx, 0); | |
1080 | ||
1081 | if (MsgType < EAPOL_GROUP_MSG_1) { | |
1082 | DBGPRINT(RT_DEBUG_ERROR, | |
1083 | ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", | |
1084 | MsgType)); | |
1085 | } else { | |
1086 | DBGPRINT(RT_DEBUG_ERROR, | |
1087 | ("Replay Counter Different in group msg %d of 2-way handshake!\n", | |
1088 | (MsgType - EAPOL_PAIR_MSG_4))); | |
ca97b838 BZ |
1089 | } |
1090 | ||
96b3c83d BZ |
1091 | hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, |
1092 | LEN_KEY_DESC_REPLAY); | |
1093 | hex_dump("Current replay counter ", pEntry->R_Counter, | |
1094 | LEN_KEY_DESC_REPLAY); | |
1095 | return FALSE; | |
ca97b838 | 1096 | } |
ec278fa2 | 1097 | /* 2. Verify MIC except Pairwise Msg1 */ |
96b3c83d | 1098 | if (MsgType != EAPOL_PAIR_MSG_1) { |
51126deb | 1099 | u8 rcvd_mic[LEN_KEY_DESC_MIC]; |
ca97b838 | 1100 | |
ec278fa2 | 1101 | /* Record the received MIC for check later */ |
96b3c83d BZ |
1102 | NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, |
1103 | LEN_KEY_DESC_MIC); | |
ca97b838 BZ |
1104 | NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); |
1105 | ||
ec278fa2 | 1106 | if (EapolKeyInfo.KeyDescVer == DESC_TYPE_TKIP) /* TKIP */ |
96b3c83d | 1107 | { |
51126deb | 1108 | HMAC_MD5(pEntry->PTK, LEN_EAP_MICK, (u8 *)pMsg, |
96b3c83d | 1109 | MsgLen, mic, MD5_DIGEST_SIZE); |
ec278fa2 | 1110 | } else if (EapolKeyInfo.KeyDescVer == DESC_TYPE_AES) /* AES */ |
96b3c83d | 1111 | { |
51126deb | 1112 | HMAC_SHA1(pEntry->PTK, LEN_EAP_MICK, (u8 *)pMsg, |
96b3c83d BZ |
1113 | MsgLen, digest, SHA1_DIGEST_SIZE); |
1114 | NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); | |
1115 | } | |
1116 | ||
1117 | if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC)) { | |
ec278fa2 | 1118 | /* send wireless event - for MIC different */ |
ca97b838 | 1119 | if (pAd->CommonCfg.bWirelessEvent) |
96b3c83d BZ |
1120 | RTMPSendWirelessEvent(pAd, |
1121 | IW_MIC_DIFF_EVENT_FLAG, | |
1122 | pEntry->Addr, | |
1123 | pEntry->apidx, 0); | |
1124 | ||
1125 | if (MsgType < EAPOL_GROUP_MSG_1) { | |
1126 | DBGPRINT(RT_DEBUG_ERROR, | |
1127 | ("MIC Different in pairwise msg %d of 4-way handshake!\n", | |
1128 | MsgType)); | |
1129 | } else { | |
1130 | DBGPRINT(RT_DEBUG_ERROR, | |
1131 | ("MIC Different in group msg %d of 2-way handshake!\n", | |
1132 | (MsgType - EAPOL_PAIR_MSG_4))); | |
ca97b838 BZ |
1133 | } |
1134 | ||
1135 | hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC); | |
1136 | hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC); | |
1137 | ||
1138 | return FALSE; | |
96b3c83d | 1139 | } |
ca97b838 | 1140 | } |
ec278fa2 BZ |
1141 | /* 1. Decrypt the Key Data field if GTK is included. */ |
1142 | /* 2. Extract the context of the Key Data field if it exist. */ | |
1143 | /* The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is clear. */ | |
1144 | /* The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted. */ | |
51126deb | 1145 | if (CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyDataLen) > 0) { |
ec278fa2 | 1146 | /* Decrypt this field */ |
96b3c83d BZ |
1147 | if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) |
1148 | || (MsgType == EAPOL_GROUP_MSG_1)) { | |
1149 | if ((EapolKeyInfo.KeyDescVer == DESC_TYPE_AES)) { | |
ec278fa2 | 1150 | /* AES */ |
ca97b838 | 1151 | AES_GTK_KEY_UNWRAP(&pEntry->PTK[16], KEYDATA, |
51126deb | 1152 | CONV_ARRARY_TO_u16(pMsg-> |
96b3c83d BZ |
1153 | KeyDesc. |
1154 | KeyDataLen), | |
1155 | pMsg->KeyDesc.KeyData); | |
1156 | } else { | |
51126deb BZ |
1157 | int i; |
1158 | u8 Key[32]; | |
ec278fa2 BZ |
1159 | /* Decrypt TKIP GTK */ |
1160 | /* Construct 32 bytes RC4 Key */ | |
ca97b838 BZ |
1161 | NdisMoveMemory(Key, pMsg->KeyDesc.KeyIv, 16); |
1162 | NdisMoveMemory(&Key[16], &pEntry->PTK[16], 16); | |
96b3c83d BZ |
1163 | ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, |
1164 | 32); | |
ec278fa2 | 1165 | /*discard first 256 bytes */ |
96b3c83d BZ |
1166 | for (i = 0; i < 256; i++) |
1167 | ARCFOUR_BYTE(&pAd->PrivateInfo. | |
1168 | WEPCONTEXT); | |
ec278fa2 | 1169 | /* Decrypt GTK. Becareful, there is no ICV to check the result is correct or not */ |
96b3c83d BZ |
1170 | ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, |
1171 | KEYDATA, pMsg->KeyDesc.KeyData, | |
51126deb | 1172 | CONV_ARRARY_TO_u16(pMsg-> |
96b3c83d BZ |
1173 | KeyDesc. |
1174 | KeyDataLen)); | |
ca97b838 BZ |
1175 | } |
1176 | ||
1177 | if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) | |
1178 | GroupKeyIndex = EapolKeyInfo.KeyIndex; | |
1179 | ||
96b3c83d BZ |
1180 | } else if ((MsgType == EAPOL_PAIR_MSG_2) |
1181 | || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2)) { | |
1182 | NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, | |
51126deb | 1183 | CONV_ARRARY_TO_u16(pMsg->KeyDesc. |
96b3c83d BZ |
1184 | KeyDataLen)); |
1185 | } else { | |
ca97b838 BZ |
1186 | |
1187 | return TRUE; | |
1188 | } | |
1189 | ||
ec278fa2 BZ |
1190 | /* Parse Key Data field to */ |
1191 | /* 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2) */ | |
1192 | /* 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2 */ | |
1193 | /* 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2) */ | |
ca97b838 | 1194 | if (!RTMPParseEapolKeyData(pAd, KEYDATA, |
51126deb | 1195 | CONV_ARRARY_TO_u16(pMsg->KeyDesc. |
96b3c83d BZ |
1196 | KeyDataLen), |
1197 | GroupKeyIndex, MsgType, bWPA2, | |
1198 | pEntry)) { | |
ca97b838 BZ |
1199 | return FALSE; |
1200 | } | |
1201 | } | |
1202 | ||
1203 | return TRUE; | |
1204 | ||
1205 | } |