diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h index 1b1486ebde..da8c3bc368 100644 --- a/core/mac/src/include/parser_api.h +++ b/core/mac/src/include/parser_api.h @@ -59,6 +59,13 @@ #define NSS_2x2_MODE 2 #define MBO_IE_ASSOC_DISALLOWED_SUBATTR_ID 0x04 +#define SIZE_OF_FIXED_PARAM 12 +#define SIZE_OF_TAG_PARAM_NUM 1 +#define SIZE_OF_TAG_PARAM_LEN 1 +#define RSNIEID 0x30 +#define RSNIE_CAPABILITY_LEN 2 +#define DEFAULT_RSNIE_CAP_VAL 0x00 + #ifdef FEATURE_AP_MCC_CH_AVOIDANCE #define QCOM_VENDOR_IE_MCC_AVOID_CH 0x01 @@ -951,4 +958,10 @@ tSirRetStatus populate_dot11f_timing_advert_frame(tpAniSirGlobal pMac, void populate_dot11_supp_operating_classes(tpAniSirGlobal mac_ptr, tDot11fIESuppOperatingClasses *dot_11_ptr, tpPESession session_entry); +tSirRetStatus +sir_validate_and_rectify_ies(tpAniSirGlobal mac_ctx, + uint8_t *mgmt_frame, + uint32_t frame_bytes, + uint32_t *missing_rsn_bytes); + #endif /* __PARSE_H__ */ diff --git a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c index 19978be544..a983f7f4ee 100644 --- a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c @@ -52,14 +52,42 @@ #include "parser_api.h" -tSirRetStatus lim_validate_ie_information_in_probe_rsp_frame(uint8_t *pRxPacketInfo) +/** + * lim_validate_ie_information_in_probe_rsp_frame () - validates ie + * information in probe response. + * @mac_ctx: mac context + * @pRxPacketInfo: Rx packet info + * + * Return: 0 on success, one on failure + */ +tSirRetStatus +lim_validate_ie_information_in_probe_rsp_frame(tpAniSirGlobal mac_ctx, + uint8_t *pRxPacketInfo) { tSirRetStatus status = eSIR_SUCCESS; + uint8_t *pframe; + uint32_t nframe; + uint32_t missing_rsn_bytes; + + /* + * Validate a Probe response frame for malformed frame. + * If the frame is malformed then do not consider as it + * may cause problem fetching wrong IE values + */ if (WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) < - (SIR_MAC_B_PR_SSID_OFFSET + SIR_MAC_MIN_IE_LEN)) { - status = eSIR_FAILURE; - } + (SIR_MAC_B_PR_SSID_OFFSET + SIR_MAC_MIN_IE_LEN)) + return eSIR_FAILURE; + + pframe = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + nframe = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + missing_rsn_bytes = 0; + + status = sir_validate_and_rectify_ies(mac_ctx, + pframe, nframe, &missing_rsn_bytes); + + if (status == eSIR_SUCCESS) + WMA_GET_RX_MPDU_LEN(pRxPacketInfo) += missing_rsn_bytes; return status; } @@ -116,7 +144,8 @@ lim_process_probe_rsp_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_Packet_info, MAC_ADDR_ARRAY(header->sa)); /* Validate IE information before processing Probe Response Frame */ - if (lim_validate_ie_information_in_probe_rsp_frame(rx_Packet_info) != + if (lim_validate_ie_information_in_probe_rsp_frame(mac_ctx, + rx_Packet_info) != eSIR_SUCCESS) { lim_log(mac_ctx, LOG1, FL("Parse error ProbeResponse, length=%d"), frame_len); @@ -346,7 +375,8 @@ lim_process_probe_rsp_frame_no_session(tpAniSirGlobal mac_ctx, lim_print_mac_addr(mac_ctx, header->sa, LOG2); /* Validate IE information before processing Probe Response Frame */ - if (lim_validate_ie_information_in_probe_rsp_frame(rx_packet_info) != + if (lim_validate_ie_information_in_probe_rsp_frame(mac_ctx, + rx_packet_info) != eSIR_SUCCESS) { lim_log(mac_ctx, LOG1, FL("Parse error ProbeResponse, length=%d"), frame_len); diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index ea28db9032..7c7bc5314b 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -2225,6 +2225,71 @@ sir_convert_probe_req_frame2_struct(tpAniSirGlobal pMac, return eSIR_SUCCESS; } /* End sir_convert_probe_req_frame2_struct. */ + +/** + * sir_validate_and_rectify_ies() - API to check malformed frame + * @mac_ctx: mac context + * @mgmt_frame: pointer to management frame + * @frame_bytes: no of bytes in frame + * @missing_rsn_bytes: missing rsn bytes + * + * The frame would contain fixed IEs of 12 bytes followed by variable IEs + * (Tagged elements). Every Tagged IE has tag number, tag length and data. + * Tag length indicates the size of data in bytes. + * This function checks for size of Frame received with the sum of all IEs. + * And also rectifies missing optional fields in IE. + * + * NOTE : Presently this function rectifies RSN capability in RSN IE, can + * be extended to rectify other optional fields in other IEs. + * + * Return: 0 on success, error number otherwise. + */ +tSirRetStatus +sir_validate_and_rectify_ies(tpAniSirGlobal mac_ctx, + uint8_t *mgmt_frame, + uint32_t frame_bytes, + uint32_t *missing_rsn_bytes) +{ + uint32_t length = SIZE_OF_FIXED_PARAM; + uint8_t *ref_frame; + + /* Frame contains atleast one IE */ + if (frame_bytes > (SIZE_OF_FIXED_PARAM + + SIZE_OF_TAG_PARAM_NUM + SIZE_OF_TAG_PARAM_LEN)) { + while (length < frame_bytes) { + /* ref frame points to next IE */ + ref_frame = mgmt_frame + length; + length += (uint32_t)(SIZE_OF_TAG_PARAM_NUM + + SIZE_OF_TAG_PARAM_LEN + + (*(ref_frame + SIZE_OF_TAG_PARAM_NUM))); + } + if (length != frame_bytes) { + /* + * Workaround : Some APs may not include RSN + * Capability but the length of which is included in + * RSN IE length. This may cause in updating RSN + * Capability with junk value. To avoid this, add RSN + * Capability value with default value. + */ + if ((*ref_frame == RSNIEID) && + (length == (frame_bytes + + RSNIE_CAPABILITY_LEN))) { + /* Assume RSN Capability as 00 */ + qdf_mem_set((uint8_t *)(mgmt_frame + + (frame_bytes)), + RSNIE_CAPABILITY_LEN, + DEFAULT_RSNIE_CAP_VAL); + *missing_rsn_bytes = RSNIE_CAPABILITY_LEN; + lim_log(mac_ctx, LOG1, + FL("Added RSN Capability to RSNIE as 0x00 0x00")); + return eSIR_SUCCESS; + } + return eSIR_FAILURE; + } + } + return eSIR_SUCCESS; +} + tSirRetStatus sir_convert_probe_frame2_struct(tpAniSirGlobal pMac, uint8_t *pFrame, uint32_t nFrame,