blob: d3df1d31eba3729580f9e10ea4e00d4d5f00f831 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2011-2015 The Linux Foundation. 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 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/*
29 *
30 * This file lim_process_probe_rsp_frame.cc contains the code
31 * for processing Probe Response Frame.
32 * Author: Chandra Modumudi
33 * Date: 03/01/02
34 * History:-
35 * Date Modified by Modification Information
36 * --------------------------------------------------------------------
37 *
38 */
39
40#include "wni_api.h"
41#include "wni_cfg.h"
42#include "ani_global.h"
43#include "sch_api.h"
44#include "utils_api.h"
45#include "lim_api.h"
46#include "lim_types.h"
47#include "lim_utils.h"
48#include "lim_assoc_utils.h"
49#include "lim_prop_exts_utils.h"
50#include "lim_ser_des_utils.h"
51#include "lim_send_messages.h"
52
53#include "parser_api.h"
54
55tSirRetStatus lim_validate_ie_information_in_probe_rsp_frame(uint8_t *pRxPacketInfo)
56{
57 tSirRetStatus status = eSIR_SUCCESS;
58
59 if (WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) <
60 (SIR_MAC_B_PR_SSID_OFFSET + SIR_MAC_MIN_IE_LEN)) {
61 status = eSIR_FAILURE;
62 }
63
64 return status;
65}
66
67/**
68 * lim_process_probe_rsp_frame() - processes received Probe Response frame
69 * @mac_ctx: Pointer to Global MAC structure
70 * @rx_Packet_info: A pointer to Buffer descriptor + associated PDUs
71 * @session_entry: Handle to the session.
72 *
73 * This function processes received Probe Response frame.
74 * Frames with out-of-order IEs are dropped.
75 * In case of IBSS, join 'success' makes MLM state machine
76 * transition into 'BSS started' state. This may have to change
77 * depending on supporting what kinda Authentication in IBSS.
78 *
79 * Return: None
80 */
81void
82lim_process_probe_rsp_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_Packet_info,
83 tpPESession session_entry)
84{
85 uint8_t *body;
86 uint32_t frame_len = 0;
87 tSirMacAddr current_bssid;
88 tpSirMacMgmtHdr header;
89 tSirProbeRespBeacon *probe_rsp;
90 uint8_t qos_enabled = false;
91 uint8_t wme_enabled = false;
92
93 if (!session_entry) {
94 lim_log(mac_ctx, LOGE, FL("session_entry is NULL"));
95 return;
96 }
97 lim_log(mac_ctx, LOG1, "SessionId:%d ProbeRsp Frame is received",
98 session_entry->peSessionId);
99
100 probe_rsp = cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
101 if (NULL == probe_rsp) {
102 lim_log(mac_ctx, LOGE,
103 FL
104 ("Unable to allocate memory "));
105 return;
106 }
107
108 probe_rsp->ssId.length = 0;
109 probe_rsp->wpa.length = 0;
110
111 header = WMA_GET_RX_MAC_HEADER(rx_Packet_info);
112
113 lim_log(mac_ctx, LOG2,
114 FL("Rx Probe Response with length = %d from "MAC_ADDRESS_STR),
115 WMA_GET_RX_MPDU_LEN(rx_Packet_info),
116 MAC_ADDR_ARRAY(header->sa));
117
118 /* Validate IE information before processing Probe Response Frame */
119 if (lim_validate_ie_information_in_probe_rsp_frame(rx_Packet_info) !=
120 eSIR_SUCCESS) {
121 lim_log(mac_ctx, LOG1,
122 FL("Parse error ProbeResponse, length=%d"), frame_len);
123 cdf_mem_free(probe_rsp);
124 return;
125 }
126
127 frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_Packet_info);
128 CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
129 FL("Probe Resp Frame Received: BSSID "
130 MAC_ADDRESS_STR " (RSSI %d)"),
131 MAC_ADDR_ARRAY(header->bssId),
132 (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_Packet_info)));
133 /* Get pointer to Probe Response frame body */
134 body = WMA_GET_RX_MPDU_DATA(rx_Packet_info);
135 /* Enforce Mandatory IEs */
136 if ((sir_convert_probe_frame2_struct(mac_ctx,
137 body, frame_len, probe_rsp) == eSIR_FAILURE) ||
138 !probe_rsp->ssidPresent) {
139 lim_log(mac_ctx, LOG1,
140 FL("Parse error ProbeResponse, length=%d"), frame_len);
141 cdf_mem_free(probe_rsp);
142 return;
143 }
144 lim_check_and_add_bss_description(mac_ctx, probe_rsp,
145 rx_Packet_info, false, true);
146 /* To Support BT-AMP */
147 if ((mac_ctx->lim.gLimMlmState ==
148 eLIM_MLM_WT_PROBE_RESP_STATE) ||
149 (mac_ctx->lim.gLimMlmState ==
150 eLIM_MLM_PASSIVE_SCAN_STATE)) {
151 lim_check_and_add_bss_description(mac_ctx, probe_rsp,
152 rx_Packet_info, ((mac_ctx->lim.
153 gLimHalScanState == eLIM_HAL_SCANNING_STATE)
154 ? true : false), true);
155 } else if (session_entry->limMlmState ==
156 eLIM_MLM_WT_JOIN_BEACON_STATE) {
157 /*
158 * Either Beacon/probe response is required.
159 * Hence store it in same buffer.
160 */
161 if (session_entry->beacon != NULL) {
162 cdf_mem_free(session_entry->beacon);
163 session_entry->beacon = NULL;
164 }
165 session_entry->bcnLen =
166 WMA_GET_RX_PAYLOAD_LEN(rx_Packet_info);
167 session_entry->beacon =
168 cdf_mem_malloc(session_entry->bcnLen);
169 if (NULL == session_entry->beacon) {
170 lim_log(mac_ctx, LOGE,
171 FL("No Memory to store beacon"));
172 } else {
173 /*
174 * Store the Beacon/ProbeRsp.
175 * This is sent to csr/hdd in join cnf response.
176 */
177 cdf_mem_copy(session_entry->beacon,
178 WMA_GET_RX_MPDU_DATA
179 (rx_Packet_info),
180 session_entry->bcnLen);
181 }
182 /* STA in WT_JOIN_BEACON_STATE */
183 lim_check_and_announce_join_success(mac_ctx, probe_rsp,
184 header,
185 session_entry);
186 } else if (session_entry->limMlmState ==
187 eLIM_MLM_LINK_ESTABLISHED_STATE) {
188 tpDphHashNode sta_ds = NULL;
189 /*
190 * Check if this Probe Response is for
191 * our Probe Request sent upon reaching
192 * heart beat threshold
193 */
194 sir_copy_mac_addr(current_bssid, session_entry->bssId);
195 if (!cdf_mem_compare(current_bssid, header->bssId,
196 sizeof(tSirMacAddr))) {
197 cdf_mem_free(probe_rsp);
198 return;
199 }
200 if (!LIM_IS_CONNECTION_ACTIVE(session_entry)) {
201 lim_log(mac_ctx, LOGW,
202 FL("Recved Probe Resp from AP,AP-alive"));
203 if (probe_rsp->HTInfo.present)
204 lim_received_hb_handler(mac_ctx,
205 probe_rsp->HTInfo.primaryChannel,
206 session_entry);
207 else
208 lim_received_hb_handler(mac_ctx,
209 (uint8_t)probe_rsp->channelNumber,
210 session_entry);
211 }
212 if (LIM_IS_STA_ROLE(session_entry)) {
213 if (probe_rsp->channelSwitchPresent) {
214 lim_update_channel_switch(mac_ctx,
215 probe_rsp,
216 session_entry);
217 } else if (session_entry->gLimSpecMgmt.dot11hChanSwState
218 == eLIM_11H_CHANSW_RUNNING) {
219 lim_cancel_dot11h_channel_switch(
220 mac_ctx, session_entry);
221 }
222 }
223 /*
224 * Now Process EDCA Parameters, if EDCAParamSet
225 * count is different.
226 * -- While processing beacons in link established
227 * state if it is determined that
228 * QoS Info IE has a different count for EDCA Params,
229 * and EDCA IE is not present in beacon,
230 * then probe req is sent out to get the EDCA params.
231 */
232 sta_ds = dph_get_hash_entry(mac_ctx,
233 DPH_STA_HASH_INDEX_PEER,
234 &session_entry->dph.dphHashTable);
235 limGetQosMode(session_entry, &qos_enabled);
236 limGetWmeMode(session_entry, &wme_enabled);
237 lim_log(mac_ctx, LOG2,
238 FL("wmeEdcaPresent: %d wme_enabled: %d"),
239 probe_rsp->wmeEdcaPresent, wme_enabled);
240 lim_log(mac_ctx, LOG2,
241 FL("edcaPresent: %d, qos_enabled: %d"),
242 probe_rsp->edcaPresent, qos_enabled);
243 lim_log(mac_ctx, LOG2,
244 FL("edcaParams.qosInfo.count: %d"),
245 probe_rsp->edcaParams.qosInfo.count);
246 lim_log(mac_ctx, LOG2,
247 FL("schObject.gLimEdcaParamSetCount: %d"),
248 session_entry->gLimEdcaParamSetCount);
249 if (((probe_rsp->wmeEdcaPresent && wme_enabled) ||
250 (probe_rsp->edcaPresent && qos_enabled)) &&
251 (probe_rsp->edcaParams.qosInfo.count !=
252 session_entry->gLimEdcaParamSetCount)) {
253 if (sch_beacon_edca_process(mac_ctx,
254 &probe_rsp->edcaParams,
255 session_entry) != eSIR_SUCCESS) {
256 lim_log(mac_ctx, LOGE,
257 FL("EDCA param process error"));
258 } else if (sta_ds != NULL) {
259 /*
260 * If needed, downgrade the
261 * EDCA parameters
262 */
263 lim_set_active_edca_params(mac_ctx,
264 session_entry->
265 gLimEdcaParams,
266 session_entry);
267 lim_send_edca_params(mac_ctx,
268 session_entry->
269 gLimEdcaParamsActive,
270 sta_ds->bssId);
271 } else {
272 lim_log(mac_ctx, LOGE,
273 FL("SelfEntry missing in Hash"));
274 }
275 }
276 if (session_entry->fWaitForProbeRsp == true) {
277 lim_log(mac_ctx, LOGW,
278 FL("Check probe resp for caps change"));
279 lim_detect_change_in_ap_capabilities(
280 mac_ctx, probe_rsp, session_entry);
281 }
282 } else {
283 if (LIM_IS_IBSS_ROLE(session_entry) &&
284 (session_entry->limMlmState ==
285 eLIM_MLM_BSS_STARTED_STATE))
286 lim_handle_ibss_coalescing(mac_ctx, probe_rsp,
287 rx_Packet_info, session_entry);
288 }
289 cdf_mem_free(probe_rsp);
290
291 /* Ignore Probe Response frame in all other states */
292 return;
293}
294
295/**
296 * lim_process_probe_rsp_frame_no_session() - process Probe Response frame
297 * @mac_ctx: Pointer to Global MAC structure
298 * @rx_packet_info: A pointer to Buffer descriptor + associated PDUs
299 *
300 * This function processes received Probe Response frame with no session.
301 *
302 * Return: None
303 */
304void
305lim_process_probe_rsp_frame_no_session(tpAniSirGlobal mac_ctx,
306 uint8_t *rx_packet_info)
307{
308 uint8_t *body;
309 uint32_t frame_len = 0;
310 tpSirMacMgmtHdr header;
311 tSirProbeRespBeacon *probe_rsp;
312
313 probe_rsp = cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
314 if (NULL == probe_rsp) {
315 lim_log(mac_ctx, LOGE,
316 FL("Unable to allocate memory"));
317 return;
318 }
319
320 probe_rsp->ssId.length = 0;
321 probe_rsp->wpa.length = 0;
322
323 header = WMA_GET_RX_MAC_HEADER(rx_packet_info);
324
325 lim_log(mac_ctx, LOG2,
326 FL("Received Probe Response frame with length=%d from "),
327 WMA_GET_RX_MPDU_LEN(rx_packet_info));
328 lim_print_mac_addr(mac_ctx, header->sa, LOG2);
329
330 /* Validate IE information before processing Probe Response Frame */
331 if (lim_validate_ie_information_in_probe_rsp_frame(rx_packet_info) !=
332 eSIR_SUCCESS) {
333 lim_log(mac_ctx, LOG1,
334 FL("Parse error ProbeResponse, length=%d"), frame_len);
335 cdf_mem_free(probe_rsp);
336 return;
337 }
338
339 frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_packet_info);
340 CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
341 FL("Probe Resp Frame Received: BSSID "
342 MAC_ADDRESS_STR " (RSSI %d)"),
343 MAC_ADDR_ARRAY(header->bssId),
344 (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_packet_info)));
345 /*
346 * Get pointer to Probe Response frame body
347 */
348 body = WMA_GET_RX_MPDU_DATA(rx_packet_info);
349 if (sir_convert_probe_frame2_struct(mac_ctx, body, frame_len,
350 probe_rsp) == eSIR_FAILURE) {
351 lim_log(mac_ctx, LOG1,
352 FL("Parse error ProbeResponse, length=%d\n"),
353 frame_len);
354 cdf_mem_free(probe_rsp);
355 return;
356 }
357 lim_log(mac_ctx, LOG2, FL("Save this probe rsp in LFR cache"));
358 lim_check_and_add_bss_description(mac_ctx, probe_rsp,
359 rx_packet_info, false, true);
360 cdf_mem_free(probe_rsp);
361 return;
362}