blob: 1147e90f44eb488d0f6ff11f97edda4e25d5fa4e [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
2 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 *
24 * Airgo Networks, Inc proprietary. All rights reserved.
25 * This file limProcessDeauthFrame.cc contains the code
26 * for processing Deauthentication Frame.
27 * Author: Chandra Modumudi
28 * Date: 03/24/02
29 * History:-
30 * Date Modified by Modification Information
31 * --------------------------------------------------------------------
32 *
33 */
34#include "palTypes.h"
35#include "aniGlobal.h"
36
37#include "utilsApi.h"
38#include "limTypes.h"
39#include "limUtils.h"
40#include "limAssocUtils.h"
41#include "limSecurityUtils.h"
42#include "limSerDesUtils.h"
43#include "schApi.h"
44#include "limSendMessages.h"
45
46
47
48/**
49 * limProcessDeauthFrame
50 *
51 *FUNCTION:
52 * This function is called by limProcessMessageQueue() upon
53 * Deauthentication frame reception.
54 *
55 *LOGIC:
56 *
57 *ASSUMPTIONS:
58 *
59 *NOTE:
60 *
61 * @param pMac - Pointer to Global MAC structure
62 * @param *pRxPacketInfo - A pointer to Buffer descriptor + associated PDUs
63 * @return None
64 */
65
66void
67limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry)
68{
69 tANI_U8 *pBody;
70 tANI_U16 aid, reasonCode;
71 tpSirMacMgmtHdr pHdr;
72 tLimMlmAssocCnf mlmAssocCnf;
73 tLimMlmDeauthInd mlmDeauthInd;
74 tpDphHashNode pStaDs;
75
76
77 pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
78
79 pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
80
81
82 if ((eLIM_STA_ROLE == psessionEntry->limSystemRole) && (eLIM_SME_WT_DEAUTH_STATE == psessionEntry->limSmeState))
83 {
84 PELOGE(limLog(pMac, LOGE,
85 FL("received Deauth frame in DEAUTH_WT_STATE(already processing previously received DEAUTH frame).. Dropping this..\n "));)
86 return;
87 }
88
89 if (limIsGroupAddr(pHdr->sa))
90 {
91 // Received Deauth frame from a BC/MC address
92 // Log error and ignore it
93 PELOG1(limLog(pMac, LOG1,
94 FL("received Deauth frame from a BC/MC address\n"));)
95
96 return;
97 }
98
99 if (limIsGroupAddr(pHdr->da) && !limIsAddrBC(pHdr->da))
100 {
101 // Received Deauth frame for a MC address
102 // Log error and ignore it
103 PELOG1(limLog(pMac, LOG1,
104 FL("received Deauth frame for a MC address\n"));)
105
106 return;
107 }
108 // Get reasonCode from Deauthentication frame body
109 reasonCode = sirReadU16(pBody);
110
111 PELOGE(limLog(pMac, LOGE,
112 FL("received Deauth frame (mlm state = %s) with reason code %d from "),
113 limMlmStateStr(pMac->lim.gLimMlmState), reasonCode);
114 limPrintMacAddr(pMac, pHdr->sa, LOGE);)
115
116 if ( (psessionEntry->limSystemRole == eLIM_AP_ROLE )||(psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) )
117 {
118 switch (reasonCode)
119 {
120 case eSIR_MAC_UNSPEC_FAILURE_REASON:
121 case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON:
122 // Valid reasonCode in received Deauthentication frame
123 break;
124
125 default:
126 // Invalid reasonCode in received Deauthentication frame
127 // Log error and ignore the frame
128 PELOG1(limLog(pMac, LOG1,
129 FL("received Deauth frame with invalid reasonCode %d from \n"),
130 reasonCode);
131 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
132
133 break;
134 }
135 }
136 else if (psessionEntry->limSystemRole == eLIM_STA_ROLE ||psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE)
137 {
138 switch (reasonCode)
139 {
140 case eSIR_MAC_UNSPEC_FAILURE_REASON:
141 case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON:
142 case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON:
143 case eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON:
144 case eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON:
145 case eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON:
146 // Valid reasonCode in received Deauth frame
147 break;
148
149 default:
150 // Invalid reasonCode in received Deauth frame
151 // Log error and ignore the frame
152 PELOG1(limLog(pMac, LOG1,
153 FL("received Deauth frame with invalid reasonCode %d from \n"),
154 reasonCode);
155 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
156
157 break;
158 }
159 }
160 else
161 {
162 // Received Deauth frame in either IBSS
163 // or un-known role. Log error and ignore it
164 limLog(pMac, LOGE,
165 FL("received Deauth frame with reasonCode %d in role %d from \n"),
166 reasonCode, psessionEntry->limSystemRole);
167 limPrintMacAddr(pMac, pHdr->sa, LOGE);
168
169 return;
170 }
171
172 /** If we are in the middle of ReAssoc, a few things could happen:
173 * - STA is reassociating to current AP, and receives deauth from:
174 * a) current AP
175 * b) other AP
176 * - STA is reassociating to a new AP, and receives deauth from:
177 * c) current AP
178 * d) reassoc AP
179 * e) other AP
180 *
181 * The logic is:
182 * 1) If rcv deauth from an AP other than the one we're trying to
183 * reassociate with, then drop the deauth frame (case b, c, e)
184 * 2) If rcv deauth from the "new" reassoc AP (case d), then restore
185 * context with previous AP and send SME_REASSOC_RSP failure.
186 * 3) If rcv deauth from the reassoc AP, which is also the same
187 * AP we're currently associated with (case a), then proceed
188 * with normal deauth processing.
189 */
190 if (limIsReassocInProgress(pMac,psessionEntry)) {
191 if (!IS_REASSOC_BSSID(pMac,pHdr->sa,psessionEntry)) {
192 PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from unknown/different AP while ReAssoc. Ignore \n"));)
193 return;
194 }
195
196 /** Received deauth from the new AP to which we tried to ReAssociate.
197 * Drop ReAssoc and Restore the Previous context( current connected AP).
198 */
199 if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry)) {
200 PELOGE(limLog(pMac, LOGW, FL("received DeAuth from the New AP to which ReAssoc is sent \n"));)
201 limRestorePreReassocState(pMac,
202 eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry);
203 return;
204 }
205 }
206
207
208 /* If received DeAuth from AP other than the one we're trying to join with
209 * nor associated with, then ignore deauth and delete Pre-auth entry.
210 */
211#ifdef WLAN_SOFTAP_FEATURE
212 if(psessionEntry->limSystemRole != eLIM_AP_ROLE ){
213#endif
214 if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry))
215 {
216 PELOGE(limLog(pMac, LOGE, FL("received DeAuth from an AP other than we're trying to join. Ignore. \n"));)
217 if (limSearchPreAuthList(pMac, pHdr->sa))
218 {
219 PELOGE(limLog(pMac, LOGE, FL("Preauth entry exist. Deleting... \n"));)
220 limDeletePreAuthNode(pMac, pHdr->sa);
221 }
222 return;
223 }
224#ifdef WLAN_SOFTAP_FEATURE
225 }
226#endif
227
228 // Check for pre-assoc states
229 switch (psessionEntry->limSystemRole)
230 {
231 case eLIM_STA_ROLE:
232 case eLIM_BT_AMP_STA_ROLE:
233 switch (psessionEntry->limMlmState)
234 {
235 case eLIM_MLM_WT_AUTH_FRAME2_STATE:
236 /**
237 * AP sent Deauth frame while waiting
238 * for Auth frame2. Report Auth failure
239 * to SME.
240 */
241
242 // Log error
243 PELOG1(limLog(pMac, LOG1,
244 FL("received Deauth frame with failure code %d from "),
245 reasonCode);
246 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
247
248 limRestoreFromAuthState(pMac, eSIR_SME_DEAUTH_WHILE_JOIN,
249 reasonCode,psessionEntry);
250
251 return;
252
253 case eLIM_MLM_AUTHENTICATED_STATE:
254 /// Issue Deauth Indication to SME.
255 palCopyMemory( pMac->hHdd,
256 (tANI_U8 *) &mlmDeauthInd.peerMacAddr,
257 pHdr->sa,
258 sizeof(tSirMacAddr));
259 mlmDeauthInd.reasonCode = reasonCode;
260
261 psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE;
262 MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, 0, pMac->lim.gLimMlmState));
263
264
265 limPostSmeMessage(pMac,
266 LIM_MLM_DEAUTH_IND,
267 (tANI_U32 *) &mlmDeauthInd);
268 return;
269
270 case eLIM_MLM_WT_ASSOC_RSP_STATE:
271 /**
272 * AP may have 'aged-out' our Pre-auth
273 * context. Delete local pre-auth context
274 * if any and issue ASSOC_CNF to SME.
275 */
276 if (limSearchPreAuthList(pMac, pHdr->sa))
277 limDeletePreAuthNode(pMac, pHdr->sa);
278
279 if (psessionEntry->pLimMlmJoinReq)
280 {
281 palFreeMemory( pMac->hHdd, psessionEntry->pLimMlmJoinReq);
282 psessionEntry->pLimMlmJoinReq = NULL;
283 }
284
285 mlmAssocCnf.resultCode = eSIR_SME_DEAUTH_WHILE_JOIN;
286 mlmAssocCnf.protStatusCode = reasonCode;
287
288 /* PE session Id*/
289 mlmAssocCnf.sessionId = psessionEntry->peSessionId;
290
291 psessionEntry->limMlmState =
292 psessionEntry->limPrevMlmState;
293 MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, 0, psessionEntry->limMlmState));
294
295 // Deactive Association response timeout
296 limDeactivateAndChangeTimer(
297 pMac,
298 eLIM_ASSOC_FAIL_TIMER);
299
300 limPostSmeMessage(
301 pMac,
302 LIM_MLM_ASSOC_CNF,
303 (tANI_U32 *) &mlmAssocCnf);
304
305 return;
306
307 case eLIM_MLM_IDLE_STATE:
308 case eLIM_MLM_LINK_ESTABLISHED_STATE:
309 /**
310 * This could be Deauthentication frame from
311 * a BSS with which pre-authentication was
312 * performed. Delete Pre-auth entry if found.
313 */
314 if (limSearchPreAuthList(pMac, pHdr->sa))
315 limDeletePreAuthNode(pMac, pHdr->sa);
316
317 break;
318
319 case eLIM_MLM_WT_REASSOC_RSP_STATE:
320 break;
321
322 case eLIM_MLM_WT_FT_REASSOC_RSP_STATE:
323 PELOG1(limLog(pMac, LOG1,
324 FL("received Deauth frame in FT state %X with reasonCode=%d from "),
325 psessionEntry->limMlmState, reasonCode);)
326 break;
327
328 default:
329 PELOG1(limLog(pMac, LOG1,
330 FL("received Deauth frame in state %X with reasonCode=%d from "),
331 psessionEntry->limMlmState, reasonCode);)
332 limPrintMacAddr(pMac, pHdr->sa, LOG1);
333 return;
334 }
335 break;
336
337 case eLIM_STA_IN_IBSS_ROLE:
338 break;
339
340#ifdef WLAN_SOFTAP_FEATURE
341 case eLIM_AP_ROLE:
342 break;
343#endif
344
345 default: // eLIM_AP_ROLE or eLIM_BT_AMP_AP_ROLE
346
347#if (WNI_POLARIS_FW_PRODUCT == AP)
348 /// Check if there exists pre-auth context for this STA
349 if (limSearchPreAuthList(pMac, pHdr->sa) == NULL)
350 {
351 /**
352 * Received Deauthentication from a STA that is neither
353 * Associated nor Pre-authenticated. Log error,
354 * and ignore Deauthentication frame.
355 */
356 PELOG1(limLog(pMac, LOG1,
357 FL("received Deauth frame from peer that does not have context, addr "));
358 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
359 }
360 else
361 {
362 /// Delete STA from pre-auth STA list
363 limDeletePreAuthNode(pMac,
364 pHdr->sa);
365
366 palCopyMemory( pMac->hHdd,
367 (tANI_U8 *) &mlmDeauthInd.peerMacAddr,
368 pHdr->sa,
369 sizeof(tSirMacAddr));
370 mlmDeauthInd.reasonCode = reasonCode;
371 mlmDeauthInd.aid = 0;
372
373 limPostSmeMessage(pMac,
374 LIM_MLM_DEAUTH_IND,
375 (tANI_U32 *) &mlmDeauthInd);
376 }
377#endif
378
379 return;
380 } // end switch (pMac->lim.gLimSystemRole)
381
382
383
384 /**
385 * Extract 'associated' context for STA, if any.
386 * This is maintained by DPH and created by LIM.
387 */
388 if( (pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable)) == NULL)
389 return;
390
391
392 if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
393 (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE))
394 {
395 /**
396 * Already in the process of deleting context for the peer
397 * and received Deauthentication frame. Log and Ignore.
398 */
399 PELOG1(limLog(pMac, LOG1,
400 FL("received Deauth frame from peer that is in state %X, addr "),
401 pStaDs->mlmStaContext.mlmState);
402 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
403 return;
404 }
405 pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes)reasonCode;
406 pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DEAUTH;
407
408 /// Issue Deauth Indication to SME.
409 palCopyMemory( pMac->hHdd, (tANI_U8 *) &mlmDeauthInd.peerMacAddr,
410 pStaDs->staAddr,
411 sizeof(tSirMacAddr));
412#if (WNI_POLARIS_FW_PRODUCT == AP)
413 mlmDeauthInd.aid = pStaDs->assocId;
414#endif
415 mlmDeauthInd.reasonCode = (tANI_U8) pStaDs->mlmStaContext.disassocReason;
416 mlmDeauthInd.deauthTrigger = eLIM_PEER_ENTITY_DEAUTH;
417
418
419 /* If we're in the middle of ReAssoc and received deauth from
420 * the ReAssoc AP, then notify SME by sending REASSOC_RSP with
421 * failure result code. By design, SME will then issue "Disassoc"
422 * and cleanup will happen at that time.
423 */
424 if (limIsReassocInProgress(pMac,psessionEntry)) {
425 /**
426 * AP may have 'aged-out' our Pre-auth
427 * context. Delete local pre-auth context
428 * if any and issue REASSOC_CNF to SME.
429 */
430 if (limSearchPreAuthList(pMac, pHdr->sa))
431 limDeletePreAuthNode(pMac, pHdr->sa);
432
433 if (psessionEntry->limAssocResponseData) {
434 palFreeMemory(pMac->hHdd, psessionEntry->limAssocResponseData);
435 psessionEntry->limAssocResponseData = NULL;
436 }
437
438 PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from ReAssoc AP. Issue REASSOC_CNF. \n"));)
439 limRestorePreReassocState(pMac, eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry);
440 return;
441 }
442
443 /// Deauthentication from peer MAC entity
444 limPostSmeMessage(pMac, LIM_MLM_DEAUTH_IND, (tANI_U32 *) &mlmDeauthInd);
445
446 // send eWNI_SME_DEAUTH_IND to SME
447 limSendSmeDeauthInd(pMac, pStaDs, psessionEntry);
448 return;
449
450} /*** end limProcessDeauthFrame() ***/
451