blob: 656edc348cca165d8b78e2df09de06c79339873d [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
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 limProcessDisassocFrame.cc contains the code
26 * for processing Disassocation 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 "wniApi.h"
36#include "sirApi.h"
37#include "aniGlobal.h"
38#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
39#include "halDataStruct.h"
40#endif
41#if (WNI_POLARIS_FW_PRODUCT == AP)
42#include "wniCfgAp.h"
43#else
44#include "wniCfgSta.h"
45#endif
46
47#include "utilsApi.h"
48#include "limTypes.h"
49#include "limUtils.h"
50#include "limAssocUtils.h"
51#include "limSecurityUtils.h"
52#include "limSerDesUtils.h"
53#include "limSendMessages.h"
54#include "schApi.h"
55
56
57/**
58 * limProcessDisassocFrame
59 *
60 *FUNCTION:
61 * This function is called by limProcessMessageQueue() upon
62 * Disassociation frame reception.
63 *
64 *LOGIC:
65 *
66 *ASSUMPTIONS:
67 * DPH drops packets for STA with 'valid' bit in pStaDs set to '0'.
68 *
69 *NOTE:
70 *
71 * @param pMac - Pointer to Global MAC structure
72 * @param *pRxPacketInfo - A pointer to Rx packet info structure
73 * @return None
74 */
75void
76limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry)
77{
78 tANI_U8 *pBody;
79 tANI_U16 aid, reasonCode;
80 tpSirMacMgmtHdr pHdr;
81 tpDphHashNode pStaDs;
82 tLimMlmDisassocInd mlmDisassocInd;
83
84
85 pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
86 pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
87
88
89 if (limIsGroupAddr(pHdr->sa))
90 {
91 // Received Disassoc frame from a BC/MC address
92 // Log error and ignore it
93 PELOG1(limLog(pMac, LOG1,
94 FL("received Disassoc frame from a BC/MC address\n"));)
95
96 return;
97 }
98
99 if (limIsGroupAddr(pHdr->da) && !limIsAddrBC(pHdr->da))
100 {
101 // Received Disassoc frame for a MC address
102 // Log error and ignore it
103 PELOG1(limLog(pMac, LOG1,
104 FL("received Disassoc frame for a MC address\n"));)
105
106 return;
107 }
108
109 // Get reasonCode from Disassociation frame body
110 reasonCode = sirReadU16(pBody);
111
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700112 PELOG2(limLog(pMac, LOG2,
113 FL("Received Disassoc frame (mlm state %d sme state %d), with reason code %d from "MAC_ADDRESS_STR),
114 psessionEntry->limMlmState, psessionEntry->limSmeState, reasonCode, MAC_ADDR_ARRAY(pHdr->sa));)
Jeff Johnson295189b2012-06-20 16:38:30 -0700115
116 /**
117 * Extract 'associated' context for STA, if any.
118 * This is maintained by DPH and created by LIM.
119 */
120 pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable);
121
122 if (pStaDs == NULL)
123 {
124 /**
125 * Disassociating STA is not associated.
126 * Log error.
127 */
128 PELOG1(limLog(pMac, LOG1,
129 FL("received Disassoc frame from STA that does not have context reasonCode=%d, addr "),
130 reasonCode);
131 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
132
133 return;
134 }
135
136 /** If we are in the Wait for ReAssoc Rsp state */
137 if (limIsReassocInProgress(pMac,psessionEntry)) {
138 /** If we had received the DisAssoc from,
139 * a. the Current AP during ReAssociate to different AP in same ESS
140 * b. Unknown AP
141 * drop/ignore the DisAssoc received
142 */
143 if (!IS_REASSOC_BSSID(pMac,pHdr->sa,psessionEntry)) {
144 PELOGW(limLog(pMac, LOGW, FL("Ignore the DisAssoc received, while Processing ReAssoc with different/unknown AP\n"));)
145 return;
146 }
147 /** If the Disassoc is received from the new AP to which we tried to ReAssociate
148 * Drop ReAssoc and Restore the Previous context( current connected AP).
149 */
150 if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry)) {
151 PELOGW(limLog(pMac, LOGW, FL("received Disassoc from the New AP to which ReAssoc is sent \n"));)
152 limRestorePreReassocState(pMac,
153 eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry);
154 return;
155 }
156 }
157
158 if ( (psessionEntry->limSystemRole == eLIM_AP_ROLE) ||
159 (psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) )
160 {
161 switch (reasonCode)
162 {
163 case eSIR_MAC_UNSPEC_FAILURE_REASON:
164 case eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON:
165 case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON:
166 case eSIR_MAC_MIC_FAILURE_REASON:
167 case eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON:
168 case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON:
169 case eSIR_MAC_RSN_IE_MISMATCH_REASON:
170 case eSIR_MAC_1X_AUTH_FAILURE_REASON:
171 // Valid reasonCode in received Disassociation frame
172 break;
173
174 default:
175 // Invalid reasonCode in received Disassociation frame
176 PELOG1(limLog(pMac, LOG1,
177 FL("received Disassoc frame with invalid reasonCode %d from \n"),
178 reasonCode);
179 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
180 break;
181 }
182 }
183 else if ( ((psessionEntry->limSystemRole == eLIM_STA_ROLE) ||
184 (psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE)) &&
185 ((psessionEntry->limSmeState != eLIM_SME_WT_JOIN_STATE) &&
186 (psessionEntry->limSmeState != eLIM_SME_WT_AUTH_STATE) &&
187 (psessionEntry->limSmeState != eLIM_SME_WT_ASSOC_STATE) &&
188 (psessionEntry->limSmeState != eLIM_SME_WT_REASSOC_STATE) ))
189 {
190 switch (reasonCode)
191 {
192 case eSIR_MAC_UNSPEC_FAILURE_REASON:
193 case eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON:
194 case eSIR_MAC_DISASSOC_DUE_TO_DISABILITY_REASON:
195 case eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON:
196 case eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON:
197 case eSIR_MAC_MIC_FAILURE_REASON:
198 case eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON:
199 case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON:
200 case eSIR_MAC_RSN_IE_MISMATCH_REASON:
201 case eSIR_MAC_1X_AUTH_FAILURE_REASON:
202 // Valid reasonCode in received Disassociation frame
203 break;
204
205 case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON:
206 // Valid reasonCode in received Disassociation frame
207 // as long as we're not about to channel switch
Jeff Johnsone7245742012-09-05 17:12:55 -0700208 if(psessionEntry->gLimChannelSwitch.state != eLIM_CHANNEL_SWITCH_IDLE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700209 {
210 limLog(pMac, LOGW,
211 FL("Ignoring disassoc frame due to upcoming "
212 "channel switch, from\n"),
213 reasonCode);
214 limPrintMacAddr(pMac, pHdr->sa, LOGW);
215 return;
216 }
217 break;
218
219 default:
220 // Invalid reasonCode in received Disassociation frame
221 // Log error and ignore the frame
222 PELOG1(limLog(pMac, LOG1,
223 FL("received Disassoc frame with invalid reasonCode %d from \n"),
224 reasonCode);
225 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
226 return;
227 }
228 }
229 else
230 {
231 // Received Disassociation frame in either IBSS
232 // or un-known role. Log error and ignore it
233 limLog(pMac, LOGE,
234 FL("received Disassoc frame with invalid reasonCode %d in role %d in sme state %d from \n"),
235 reasonCode, psessionEntry->limSystemRole, psessionEntry->limSmeState);
236 limPrintMacAddr(pMac, pHdr->sa, LOGE);
237
238 return;
239 }
240
241 // Disassociation from peer MAC entity
242
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700243 PELOGE(limLog(pMac, LOGE,
244 FL("Received Disassoc frame from sta with assocId=%d with reasonCode=%d. Peer MAC is "MAC_ADDRESS_STR),
245 pStaDs->assocId, reasonCode, MAC_ADDR_ARRAY(pHdr->sa));)
Jeff Johnson295189b2012-06-20 16:38:30 -0700246
247 if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
248 (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE))
249 {
250 /**
251 * Already in the process of deleting context for the peer
252 * and received Disassociation frame. Log and Ignore.
253 */
254 PELOG1(limLog(pMac, LOG1,
255 FL("received Disassoc frame in state %d from"),
256 pStaDs->mlmStaContext.mlmState);
257 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
258
259 return;
260 }
261
262 if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)
263 {
264 /**
265 * Requesting STA is in some 'transient' state?
266 * Log error.
267 */
268 PELOG1(limLog(pMac, LOG1,
269 FL("received Disassoc frame from peer that is in state %X, addr "),
270 pStaDs->mlmStaContext.mlmState);
271 limPrintMacAddr(pMac, pHdr->sa, LOG1);)
272 } // if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)
273
274 pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DISASSOC;
275 pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) reasonCode;
276
277 // Issue Disassoc Indication to SME.
278 palCopyMemory( pMac->hHdd, (tANI_U8 *) &mlmDisassocInd.peerMacAddr,
279 (tANI_U8 *) pStaDs->staAddr,
280 sizeof(tSirMacAddr));
281 mlmDisassocInd.reasonCode =
282 (tANI_U8) pStaDs->mlmStaContext.disassocReason;
283#if (WNI_POLARIS_FW_PRODUCT == AP)
284 mlmDisassocInd.aid = pStaDs->assocId;
285#endif
286 mlmDisassocInd.disassocTrigger = eLIM_PEER_ENTITY_DISASSOC;
287
288 /* Update PE session Id */
289 mlmDisassocInd.sessionId = psessionEntry->peSessionId;
290
291 if (limIsReassocInProgress(pMac,psessionEntry)) {
292
293 /* If we're in the middle of ReAssoc and received disassoc from
294 * the ReAssoc AP, then notify SME by sending REASSOC_RSP with
295 * failure result code. By design, SME will then issue "Disassoc"
296 * and cleanup will happen at that time.
297 */
298 PELOGE(limLog(pMac, LOGE, FL("received Disassoc from AP while waiting for Reassoc Rsp\n"));)
299
300 if (psessionEntry->limAssocResponseData) {
301 palFreeMemory(pMac->hHdd, psessionEntry->limAssocResponseData);
302 psessionEntry->limAssocResponseData = NULL;
303 }
304
305 limRestorePreReassocState(pMac,eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry);
306 return;
307 }
308
309 limPostSmeMessage(pMac, LIM_MLM_DISASSOC_IND,
310 (tANI_U32 *) &mlmDisassocInd);
311
312
313 // send eWNI_SME_DISASSOC_IND to SME
314 limSendSmeDisassocInd(pMac, pStaDs,psessionEntry);
315
316 return;
317} /*** end limProcessDisassocFrame() ***/
318